Compare commits

...
78 Commits
Author SHA1 Message Date
sdong 4be3b1c3e5 Disable warning as error 2019-11-05 11:08:51 -08:00
sdong f54a9a6e7f [FB Internal] Point to the latest tool chain. 2019-10-31 14:12:20 -07:00
sdong eb84ad3151 Revert "[FB Internal] Remove code for FB-only toolchain (since GCC 4.8 is everywhere already)"
This reverts commit 61720850f6.
2019-10-31 13:57:29 -07:00
sdong 50c552c5bc [FB Internal] Remove code for FB-only toolchain (since GCC 4.8 is everywhere already) 2019-10-31 13:52:51 -07:00
sdong 5b74443720 [fb only] revert unintended change of USE_SSE
The previuos change that use gcc-5 set USE_SSE to wrong flag by mistake. Fix it.
2017-07-17 22:24:39 -07:00
sdong 073cdbaa49 [FB Only] use gcc-5 2017-07-17 22:07:38 -07:00
Islam AbdelRahman e52d6ad227 bump version to 5.2.1 2017-03-15 14:30:21 -07:00
Aaron Gao 25ea289819 Reset DBIter::saved_key_ with proper user key anywhere before pass to DBIter::FindNextUserEntry
Summary:
fix db_iter bug introduced by [facebook#1413](https://github.com/facebook/rocksdb/pull/1413)
Closes https://github.com/facebook/rocksdb/pull/1962

Differential Revision: D4672369

Pulled By: lightmark

fbshipit-source-id: 6a22953
2017-03-13 10:25:42 -07:00
Siying Dong 4dd267d497 Make compaction_pri settable through option string
Summary: Closes https://github.com/facebook/rocksdb/pull/1941

Differential Revision: D4637253

Pulled By: siying

fbshipit-source-id: a59dcdb
2017-03-02 14:43:42 -08:00
sdong 32be357ef7 Update HISTORY.md for the Direct I/O fixes. 2017-02-22 15:59:46 -08:00
Aaron Gao 3eb6956728 add use_direct_io() to ReadaheadRandomAccessFile
Summary:
Missing this function will cause RandomAccessFileReader not doing alignment in Direct IO mode, which introduce an IOError: invalid argument.
Closes https://github.com/facebook/rocksdb/pull/1900

Differential Revision: D4601261

Pulled By: lightmark

fbshipit-source-id: c3eadf1
2017-02-22 15:59:17 -08:00
Aaron Gao 18ba3e2edd truncate patch
Summary:
omit the override for the previous commit
Closes https://github.com/facebook/rocksdb/pull/1898

Differential Revision: D4598743

Pulled By: lightmark

fbshipit-source-id: f98a378
2017-02-22 15:59:03 -08:00
Aaron Gao 1c91104f43 posix writablefile truncate
Summary:
we occasionally missing this call so the file size will be wrong
Closes https://github.com/facebook/rocksdb/pull/1894

Differential Revision: D4598446

Pulled By: lightmark

fbshipit-source-id: 42b6ef5
2017-02-22 15:58:42 -08:00
Yulia Kartseva e47027d92d alignment is on in ReadaheadRandomAccessFile::Read()
Summary: Closes https://github.com/facebook/rocksdb/pull/1857

Differential Revision: D4534518

Pulled By: wat-ze-hex

fbshipit-source-id: b456946
2017-02-21 10:03:53 -08:00
sdong e5fd8bdb83 Update version number and HISTORY.md 2017-02-09 14:34:30 -08:00
Maysam Yabandeh ac2a77a746 Announce the experimetnal two-level index feature in HISTORY.md
Summary:
Announce the experimetnal two-level index feature in HISTORY.md. Also updated the default for index_per_partition to 1024.
Closes https://github.com/facebook/rocksdb/pull/1855

Differential Revision: D4530102

Pulled By: maysamyabandeh

fbshipit-source-id: b0fc6ff
2017-02-08 14:24:10 -08:00
Maysam Yabandeh c4a37dcb44 Print the missed last layer in cfstats
Summary:
Printing compaction stats used to operate on two variable:
number_levels_: for printing the layer
num_levels_to_check: for updating the compaction score

After this commit: 361010d447 these two are mixed up and as a result the last layer might not be printed out: https://fb.facebook.com/groups/rocksdb.internal/permalink/1315716625143616/

number_levels_ was used to decide which layers to print: https://github.com/facebook/rocksdb/blob/672300f47f72b28c164fdf98a08171c09e311205/db/internal_stats.cc#L753 but after the patch it is based on the return value of DumpCFMapStats https://github.com/facebook/rocksdb/blob/361010d44738de48ffc4fd9add70caa0891a0719/db/internal_stats.cc#L929 which returns num_levels_to_check: https://github.com/facebook/rocksdb/blob/361010d44738de48ffc4fd9add70caa0891a0719/db/internal_stats.cc#L917
Closes https://github.com/facebook/rocksdb/pull/1853

Differential Revision: D4529280

Pulled By: maysamyabandeh

fbshipit-source-id: 3fd9448
2017-02-08 10:39:15 -08:00
Maysam Yabandeh a12818afc0 Blog post for 5.1.2 release
Summary: Closes https://github.com/facebook/rocksdb/pull/1849

Differential Revision: D4528696

Pulled By: maysamyabandeh

fbshipit-source-id: c12f3a2
2017-02-08 08:54:20 -08:00
Andrew Kryczka 3b4ac8076b Clarify ldb column family argument
Summary:
move the argument description to the right section, make it clearer that the '=' sign is required, and use it in one subcommand where it seemed forgotten before.
Closes https://github.com/facebook/rocksdb/pull/1840

Differential Revision: D4515096

Pulled By: ajkr

fbshipit-source-id: 7b5b1c1
2017-02-07 11:54:10 -08:00
Andrew Kryczka d70ce7ee0b Move db_bench flags out of unnamed namespace
Summary:
I want to be able to, e.g., DECLARE_string(statistics_string); in my application such that I can override the default value of statistics_string. For this to work, we need to remove the unnamed namespace containing all the flags, and make sure all variables/functions covered by that namespace are static.

Replaces #1828 due to internal tool issues.
Closes https://github.com/facebook/rocksdb/pull/1844

Differential Revision: D4515124

Pulled By: ajkr

fbshipit-source-id: 23b695e
2017-02-07 11:39:12 -08:00
Andrew Kryczka 186c7eedb0 Remove incorrect statistics warning
Summary:
statistics are always concurrently updated regardless of whether a single instance or multiple instances are used. remove the warning since it's unnecessarily preventing people from sharing stats objects across rocksdb instances.

replace #1819 which was having some problem with our internal tools.
Closes https://github.com/facebook/rocksdb/pull/1826

Differential Revision: D4495970

Pulled By: ajkr

fbshipit-source-id: 6601f61
2017-02-07 11:39:12 -08:00
James Sun 53bb01516d [rocksdb][PR] compaction_style and compaction_pri should output their value as a st…
Summary:
…ring

Replace the numerical output for compaction_style and compaction_pri
with strings
Closes https://github.com/facebook/rocksdb/pull/1817

Differential Revision: D4482796

Pulled By: highker

fbshipit-source-id: 5785768
2017-02-07 10:39:12 -08:00
Maysam Yabandeh 69d5262c81 Two-level Indexes
Summary:
Partition Index blocks and use a Partition-index as a 2nd level index.

The two-level index can be used by setting
BlockBasedTableOptions::kTwoLevelIndexSearch as the index type and
configuring BlockBasedTableOptions::index_per_partition

t15539501
Closes https://github.com/facebook/rocksdb/pull/1814

Differential Revision: D4473535

Pulled By: maysamyabandeh

fbshipit-source-id: bffb87e
2017-02-06 16:39:12 -08:00
Dmitri Smirnov 0a4cdde50a Windows thread
Summary:
introduce new methods into a public threadpool interface,
- allow submission of std::functions as they allow greater flexibility.
- add Joining methods to the implementation to join scheduled and submitted jobs with
  an option to cancel jobs that did not start executing.
- Remove ugly `#ifdefs` between pthread and std implementation, make it uniform.
- introduce pimpl for a drop in replacement of the implementation
- Introduce rocksdb::port::Thread typedef which is a replacement for std::thread.  On Posix Thread defaults as before std::thread.
- Implement WindowsThread that allocates memory in a more controllable manner than windows std::thread with a replaceable implementation.
- should be no functionality changes.
Closes https://github.com/facebook/rocksdb/pull/1823

Differential Revision: D4492902

Pulled By: siying

fbshipit-source-id: c74cb11
2017-02-06 14:54:18 -08:00
Vitaliy Liptchinsky 1aaa898cf1 Adding GetApproximateMemTableStats method
Summary:
Added method that returns approx num of entries as well as size for memtables.
Closes https://github.com/facebook/rocksdb/pull/1841

Differential Revision: D4511990

Pulled By: VitaliyLi

fbshipit-source-id: 9a4576e
2017-02-06 14:54:16 -08:00
Rhys Parry 9fc23c55f2 Use gcc-4.9-glibc-2.20-fb python in precommit_checker
Summary:
The gcc-4.8.1-glibc-2.17 platform is deprecated and will be removed
soon.
Closes https://github.com/facebook/rocksdb/pull/1839

Differential Revision: D4509684

Pulled By: siying

fbshipit-source-id: 3efe296
2017-02-03 13:39:18 -08:00
Andrew Kryczka b797e42157 Dump compression dictionary meta-block
Summary:
make sst_dump print size/contents of the dictionary meta-block for easier debugging
Closes https://github.com/facebook/rocksdb/pull/1837

Differential Revision: D4506399

Pulled By: ajkr

fbshipit-source-id: b9bf668
2017-02-03 12:39:16 -08:00
Siying Dong 036d668b19 Fix wrong result in data race case related to Get()
Summary:
In theory, Get() can get a wrong result, if it races in a special with with flush. The bug can be reproduced in DBTest2.GetRaceFlush. Fix this bug by getting snapshot after referencing the super version.
Closes https://github.com/facebook/rocksdb/pull/1816

Differential Revision: D4475958

Pulled By: siying

fbshipit-source-id: bd9e67a
2017-02-03 11:39:15 -08:00
Islam AbdelRahman 574b543f80 Rename merger.h -> merging_iterator.h
Summary:
merger.h was always a confusing name for me, simply give the file a better name
Closes https://github.com/facebook/rocksdb/pull/1836

Differential Revision: D4505357

Pulled By: IslamAbdelRahman

fbshipit-source-id: 07b28d8
2017-02-02 16:54:19 -08:00
Dmitri Smirnov add8b50cc9 Move ThreadLocal implementation into .cc
Summary: Closes https://github.com/facebook/rocksdb/pull/1829

Differential Revision: D4502314

Pulled By: siying

fbshipit-source-id: f46fac1
2017-02-02 14:09:12 -08:00
Siying Dong 71d2496afc Fix arc setting for Facebook internal tools
Summary: Closes https://github.com/facebook/rocksdb/pull/1834

Differential Revision: D4503469

Pulled By: siying

fbshipit-source-id: 761bfa6
2017-02-02 13:24:16 -08:00
Siying Dong f289d9f4ac Fix OSX build break after the fallocate change
Summary:
The recent update about fallocate failed OSX build. Fix it.
Closes https://github.com/facebook/rocksdb/pull/1830

Differential Revision: D4500235

Pulled By: siying

fbshipit-source-id: a5f2b40
2017-02-02 10:39:11 -08:00
Siying Dong 4a3e7d320c Change the default of delayed slowdown value to 16MB/s
Summary:
Change the default of delayed slowdown value to 16MB/s and further increase the L0 stop condition to 36 files.
Closes https://github.com/facebook/rocksdb/pull/1821

Differential Revision: D4489229

Pulled By: siying

fbshipit-source-id: 1003981
2017-02-01 20:39:17 -08:00
Siying Dong 0513e21f9b RangeSync() should work with ROCKSDB_FALLOCATE_PRESENT not set
Summary: Closes https://github.com/facebook/rocksdb/pull/1824

Differential Revision: D4493862

Pulled By: siying

fbshipit-source-id: c168446
2017-02-01 10:24:20 -08:00
Islam AbdelRahman 8b369ae5bd Cleaner default options using C++11 in-class init
Summary:
C++11 in-class initialization is cleaner and makes it the default more explicit to our users and more visible.
Use it for ColumnFamilyOptions and DBOptions
Closes https://github.com/facebook/rocksdb/pull/1822

Differential Revision: D4490473

Pulled By: IslamAbdelRahman

fbshipit-source-id: c493a87
2017-01-31 18:09:15 -08:00
Islam AbdelRahman ec79a7b53c Dedup code in option.cc and db_options.cc
Summary:
The code in DBOptions::Dump is simply a duplicate of the code in ImmutableDBOptions::Dump and MutableDBOptions.Dump

consolidate duplicate code.

tested visually
Closes https://github.com/facebook/rocksdb/pull/1818

Differential Revision: D4486710

Pulled By: IslamAbdelRahman

fbshipit-source-id: 7085189
2017-01-31 17:39:12 -08:00
oranagra b96372dead improving the C wrapper
Summary:
- rocksdb_property_int (so that we don't have to parse strings)
- and rocksdb_set_options (to allow controlling options via strings)
- a few other missing options exposed
- a documentation comment fix
Closes https://github.com/facebook/rocksdb/pull/1793

Differential Revision: D4456569

Pulled By: yiwu-arbug

fbshipit-source-id: 9f1fac1
2017-01-27 17:39:16 -08:00
Siying Dong 04c4ec41d1 Change corruption_test to use 4 bits.
Summary:
In the patch which LRU cache was made use dynamic shard bits, I changed to 2 shard bits to make the test happy. Look like it is occasionally still unhappy. Change it to 4 shard bits.
Closes https://github.com/facebook/rocksdb/pull/1815

Differential Revision: D4475849

Pulled By: siying

fbshipit-source-id: 575ff00
2017-01-27 11:24:16 -08:00
Siying Dong 2d75cd40d3 NewLRUCache() to pick number of shard bits based on capacity if not given
Summary:
If the users use the NewLRUCache() without passing in the number of shard bits, instead of using hard-coded 6, we'll determine it based on capacity.
Closes https://github.com/facebook/rocksdb/pull/1584

Differential Revision: D4242517

Pulled By: siying

fbshipit-source-id: 86b0f18
2017-01-27 06:39:12 -08:00
Siying Dong f25f1ec60b Add test DBTest2.GetRaceFlush which can expose a data race bug
Summary:
A current data race issue in Get() and Flush() can cause a Get() to return wrong results when a flush happened in the middle. Disable the test for now.
Closes https://github.com/facebook/rocksdb/pull/1813

Differential Revision: D4472310

Pulled By: siying

fbshipit-source-id: 5755ebd
2017-01-26 16:39:14 -08:00
Andrew Kryczka 37d4a79e99 Deserialize custom Statistics object in db_bench
Summary:
Added -statistics_string to deserialize a Statistics object using the factory functions registered by applications.
Closes https://github.com/facebook/rocksdb/pull/1812

Differential Revision: D4469811

Pulled By: ajkr

fbshipit-source-id: 2d80862
2017-01-26 15:24:16 -08:00
Andrew Kryczka 3b35134e4b Avoid cache lookups for range deletion meta-block
Summary:
I added the Cache::Ref() function a couple weeks ago (#1761) to make this feature possible. Like other meta-blocks, rep_->range_del_entry holds a cache handle to pin the range deletion block in uncompressed block cache for the duration of the table reader's lifetime. We can reuse this cache handle to create an iterator over this meta-block without any cache lookup. Ref() is used to increment the cache handle's refcount in case the returned iterator outlives the table reader.
Closes https://github.com/facebook/rocksdb/pull/1801

Differential Revision: D4458782

Pulled By: ajkr

fbshipit-source-id: 2883f10
2017-01-26 11:24:13 -08:00
Andrew Kryczka 94a0c32e73 Fix LRU Ref() for handles with external references only
Summary:
For case !handle->InCache() && handle->refs >= 1 (the third case mentioned in lru_cache.h), the key was overwritten by Insert(). In this case, the refcount can still be incremented, and the cache handle will never enter LRU list. Fix Ref() logic for this case.
Closes https://github.com/facebook/rocksdb/pull/1808

Differential Revision: D4467656

Pulled By: ajkr

fbshipit-source-id: c0784d8
2017-01-26 10:54:15 -08:00
Andrew Kryczka 17c1180603 Generalize Env registration framework
Summary:
The Env registration framework supports registering client Envs and selecting which one to instantiate according to a text field. This enabled things like adding the -env_uri argument to db_bench, so the same binary could be reused with different Envs just by changing CLI config.

Now this problem has come up again in a non-Env context, as I want to instantiate a client Statistics implementation from db_bench, which is configured entirely via text parameters. Also, in the future we may wish to use it for deserializing client objects when loading OPTIONS file.

This diff generalizes the Env registration logic to work with arbitrary types.

- Generalized registration and instantiation code by templating them
- The entire implementation is in a header file as that's Google style guide's recommendation for template definitions
- Pattern match with std::regex_match rather than checking prefix, which was the previous behavior
- Rename functions/files to be non-Env-specific
Closes https://github.com/facebook/rocksdb/pull/1776

Differential Revision: D4421933

Pulled By: ajkr

fbshipit-source-id: 34647d1
2017-01-25 16:09:14 -08:00
sdong 07dddd5f7e EnvPosixTestWithParam should wait for all threads to finish
Summary:
If we don't wait for the threads to finish after each run, the thread queue may not be empty while the next test starts to run, which can cause unexpected behaviors.

Also make some of the relaxed read/write more restrict.
Closes https://github.com/facebook/rocksdb/pull/1590

Reviewed By: AsyncDBConnMarkedDownDBException

Differential Revision: D4245922

Pulled By: AsyncDBConnMarkedDownDBException

fbshipit-source-id: f83b74b
2017-01-25 15:54:13 -08:00
sdong 5dad9d6d28 Avoid logs_ operation out of DB mutex
Summary:
logs_.back() is called out of DB mutex, which can cause data race. We move the access into the DB mutex protection area.
Closes https://github.com/facebook/rocksdb/pull/1774

Reviewed By: AsyncDBConnMarkedDownDBException

Differential Revision: D4417472

Pulled By: AsyncDBConnMarkedDownDBException

fbshipit-source-id: 2da1f1e
2017-01-25 15:54:13 -08:00
Islam AbdelRahman a7b13919bf Fix CompactFiles() bug when used with CompactionFilter using SuperVersion
Summary:
GetAndRefSuperVersion() should not be called again in the same thread before ReturnAndCleanupSuperVersion() is called.

If we have a compaction filter that is using DB::Get, This will happen
```
CompactFiles() {
  GetAndRefSuperVersion() // -- first call
    ..
    CompactionFilter() {
      GetAndRefSuperVersion() // -- second call
      ReturnAndCleanupSuperVersion()
    }
    ..
  ReturnAndCleanupSuperVersion()
}
```

We solve this issue in the same way Iterator is solving it, but using GetReferencedSuperVersion()

This was discovered in https://github.com/facebook/mysql-5.6/issues/427 by alxyang
Closes https://github.com/facebook/rocksdb/pull/1803

Differential Revision: D4460155

Pulled By: IslamAbdelRahman

fbshipit-source-id: 5e54322
2017-01-25 14:09:13 -08:00
Andrew Kryczka 616a1464ea Fix DeleteRange including sentinels in output files
Summary:
when writing RangeDelAggregator::AddToBuilder, I forgot that there are sentinel tombstones in the middle of the interval map since gaps between real tombstones are represented with sentinels.

blame: #1614
Closes https://github.com/facebook/rocksdb/pull/1804

Differential Revision: D4460426

Pulled By: ajkr

fbshipit-source-id: 69444b5
2017-01-25 11:09:12 -08:00
Zongzhi Chen c918c4b76a Update USERS.md add user Pika
Summary:
add rocksdb users pika
Closes https://github.com/facebook/rocksdb/pull/1805

Differential Revision: D4462809

Pulled By: siying

fbshipit-source-id: 7289886
2017-01-25 10:39:17 -08:00
Islam AbdelRahman 03ca2ac8a9 Remove function from DBImpl that are not used anywhere
Summary:
GetAndRefSuperVersionUnlocked
ReturnAndCleanupSuperVersionUnlocked
GetColumnFamilyHandleUnlocked

Are dead code that are not used any where
Closes https://github.com/facebook/rocksdb/pull/1802

Differential Revision: D4459948

Pulled By: IslamAbdelRahman

fbshipit-source-id: 30fa89d
2017-01-24 19:24:13 -08:00
Andrew Kryczka b0029bc7fa Test merge op covered by range deletion in memtable
Summary:
It's a test case for #1797. Also got rid of kTypeDeletion in the conditional since we treat it the same as kTypeRangeDeletion.
Closes https://github.com/facebook/rocksdb/pull/1800

Differential Revision: D4451300

Pulled By: ajkr

fbshipit-source-id: b39dda1
2017-01-24 13:39:11 -08:00
Andrew Kryczka d438e1ec17 Test range deletion block outlives table reader
Summary:
This test ensures RangeDelAggregator can still access blocks even if it outlives the table readers that created them (detailed description in comments).

I plan to optimize away the extra cache lookup we currently do in BlockBasedTable::NewRangeTombstoneIterator(), as it is ~5% CPU in my random read benchmark in a database with 1k tombstones. This test will help make sure nothing breaks in the process.
Closes https://github.com/facebook/rocksdb/pull/1739

Differential Revision: D4375954

Pulled By: ajkr

fbshipit-source-id: aef9357
2017-01-24 13:24:14 -08:00
Arun Sharma fba726e555 Version librocksdb.so
Summary:
After make install, I see a directory hierarchy that looks like

```
./usr
./usr/include
./usr/include/rocksdb
./usr/include/rocksdb/filter_policy.h
[..]
./usr/include/rocksdb/iterator.h
./usr/include/rocksdb/utilities
./usr/include/rocksdb/utilities/ldb_cmd_execute_result.h
./usr/include/rocksdb/utilities/lua
./usr/include/rocksdb/utilities/lua/rocks_lua_custom_library.h
./usr/include/rocksdb/utilities/lua/rocks_lua_util.h
./usr/include/rocksdb/utilities/lua/rocks_lua_compaction_filter.h
./usr/include/rocksdb/utilities/backupable_db.h
[..]
./usr/include/rocksdb/utilities/env_registry.h
[..]
./usr/include/rocksdb/env.h
./usr/lib64
./usr/lib64/librocksdb.so.5
./usr/lib64/librocksdb.so.5.0.0
./usr/lib64/librocksdb.so
./usr/lib64/librocksdb.a
```
Closes https://github.com/facebook/rocksdb/pull/1798

Differential Revision: D4456536

Pulled By: yiwu-arbug

fbshipit-source-id: 5494e91
2017-01-24 11:09:10 -08:00
Andrew Kryczka 9da4d542fe Range deletions unsupported in tailing iterator
Summary:
change the iterator status to NotSupported as soon as a range tombstone
is encountered by a ForwardIterator.
Closes https://github.com/facebook/rocksdb/pull/1593

Differential Revision: D4246294

Pulled By: ajkr

fbshipit-source-id: aef9f49
2017-01-23 13:39:12 -08:00
Hyeonseok Oh f2b4939da4 fixed typo
Summary:
I fixed exisit -> exist
Closes https://github.com/facebook/rocksdb/pull/1799

Differential Revision: D4451466

Pulled By: yiwu-arbug

fbshipit-source-id: b447c3a
2017-01-23 12:54:13 -08:00
yinqiwen 973f1b78fd memtable: delete merge value for range deleteion
Summary: Closes https://github.com/facebook/rocksdb/pull/1797

Differential Revision: D4448004

Pulled By: ajkr

fbshipit-source-id: 3ffc27c
2017-01-23 12:24:14 -08:00
jsteemann aebfd1703b fix non-portable behavior in encoder
Summary:
using ~0UL for mask uses a uint32_t at least in MSVC, but a uint64_t is required for it to work properly
Closes https://github.com/facebook/rocksdb/pull/1777

Differential Revision: D4444004

Pulled By: yiwu-arbug

fbshipit-source-id: 057cc42
2017-01-20 16:39:22 -08:00
Vitaliy Liptchinsky 753ff84a3d Fix get approx size
Summary:
Fixing GetApproximateSize bug for the case of computing stats for mem tables only.
Closes https://github.com/facebook/rocksdb/pull/1795

Differential Revision: D4445507

Pulled By: IslamAbdelRahman

fbshipit-source-id: 3905846
2017-01-20 15:54:12 -08:00
Arun Sharma d7ea44f2f9 Fixup a couple of builds errors on Linux.
Summary:
The libraries produced on linux are now named
librocksdb.a
librocksdb.so

Other fixes:

* Also link with -lrt to avoid linker errors.
* Generalize comments at the top to include Linux
* Move -lgtest before -lpthread to avoid linker errors
* move add_subdirectory(tools) to the end so it picks up
  the right libraries
Closes https://github.com/facebook/rocksdb/pull/1364

Differential Revision: D4444138

Pulled By: yiwu-arbug

fbshipit-source-id: f0e2c19
2017-01-20 13:24:13 -08:00
Jay Lee 537da370da c: allow set savepoint to writebatch
Summary:
Allow set SavePoint to WriteBatch in C ABI.
Closes https://github.com/facebook/rocksdb/pull/1698

Differential Revision: D4378556

Pulled By: yiwu-arbug

fbshipit-source-id: afca746
2017-01-20 13:24:13 -08:00
Min Wei af6ec4d78e fix batchresult handle leak
Summary:
This is related to PR https://github.com/facebook/rocksdb/pull/1642

Sorry about this extra PR, as my workflow was messed up when I checked in another work item by accident.
Closes https://github.com/facebook/rocksdb/pull/1681

Differential Revision: D4379513

Pulled By: yiwu-arbug

fbshipit-source-id: a668d4c
2017-01-20 13:24:12 -08:00
Adam Retter e29bb934f7 Zlib 1.2.8 is no longer available, switched to 1.2.10
Summary: Closes https://github.com/facebook/rocksdb/pull/1741

Differential Revision: D4380116

Pulled By: yiwu-arbug

fbshipit-source-id: 7cf09df
2017-01-20 13:24:12 -08:00
Changli Gao 5ac97314e7 Fix std::out_of_range when DBOptions::keep_log_file_num is zero
Summary:
We should validate this option, otherwise we may see
std::out_of_range thrown at: db/db_impl.cc:1124

1123     for (unsigned int i = 0; i <= end; i++) {
1124       std::string& to_delete = old_info_log_files.at(i);
1125       std::string full_path_to_delete =
1126           (immutable_db_options_.db_log_dir.empty()
Closes https://github.com/facebook/rocksdb/pull/1722

Differential Revision: D4379495

Pulled By: yiwu-arbug

fbshipit-source-id: e136552
2017-01-20 13:24:12 -08:00
Kefu Chai 4e35ffdfab cmake: check -momit-leaf-frame-pointer before using it
Summary:
because not all archs support this option. see
https://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html.

also do not pass "-fno-omit-frame-pointer" and
"-momit-leaf-frame-pointer" to compiler if ${CMAKE_BUILD_TYPE} is
"Debug". this matches the behaviour of DEBUG_LEVEL=2 in Makefile.

Signed-off-by: Kefu Chai <tchaikov@gmail.com>
Closes https://github.com/facebook/rocksdb/pull/1762

Differential Revision: D4444036

Pulled By: yiwu-arbug

fbshipit-source-id: 8596fbe
2017-01-20 13:09:11 -08:00
Shu Zhang 3c0852d1da Make ingest external file backward compatible
Summary: Closes https://github.com/facebook/rocksdb/pull/1783

Differential Revision: D4443463

Pulled By: IslamAbdelRahman

fbshipit-source-id: 39d21d6
2017-01-20 12:09:19 -08:00
Siying Dong 0e8dfd6062 Fix OptimizeForPointLookup()
Summary:
If users directly call OptimizeForPointLookup(), it is broken as the option isn't compatible with parallel memtable insert. Fix it by using memtable bloomo filter instead.
Closes https://github.com/facebook/rocksdb/pull/1791

Differential Revision: D4442836

Pulled By: siying

fbshipit-source-id: bf6c9cd
2017-01-20 10:54:12 -08:00
Vitaliy Liptchinsky e840213d6e Change DB::GetApproximateSizes for more flexibility needed for MyRocks
Summary:
Added an option to GetApproximateSizes to exclude file stats, as MyRocks has those counted exactly and we need only stats from memtables.
Closes https://github.com/facebook/rocksdb/pull/1787

Differential Revision: D4441111

Pulled By: IslamAbdelRahman

fbshipit-source-id: c11f4c3
2017-01-20 09:39:11 -08:00
Yi Wu 9239103cd4 Flush job should release reference current version if sync log failed
Summary:
Fix the bug when sync log fail, FlushJob::Run() will not be execute and
reference to cfd->current() will not be release.
Closes https://github.com/facebook/rocksdb/pull/1792

Differential Revision: D4441316

Pulled By: yiwu-arbug

fbshipit-source-id: 5523e28
2017-01-19 23:09:15 -08:00
Islam AbdelRahman da54d36a96 Disable IngestExternalFile in ReadOnly mode
Summary:
Disable IngestExternalFile() in read only mode
Closes https://github.com/facebook/rocksdb/pull/1781

Differential Revision: D4439179

Pulled By: IslamAbdelRahman

fbshipit-source-id: b7e46e7
2017-01-19 15:54:19 -08:00
Reid Horuff 5cf176ca15 Fix for 2PC causing WAL to grow too large
Summary:
Consider the following single column family scenario:
prepare in log A
commit in log B
*WAL is too large, flush all CFs to releast log A*
*CFA is on log B so we do not see CFA is depending on log A so no flush is requested*

To fix this we must also consider the log containing the prepare section when determining what log a CF is dependent on.
Closes https://github.com/facebook/rocksdb/pull/1768

Differential Revision: D4403265

Pulled By: reidHoruff

fbshipit-source-id: ce800ff
2017-01-19 15:39:12 -08:00
Islam AbdelRahman 4a73bb0b43 Split travis jobs
Summary:
Some travis jobs are running out of space, splitting to more jobs should reduce the chance of that happening
Closes https://github.com/facebook/rocksdb/pull/1789

Differential Revision: D4438039

Pulled By: IslamAbdelRahman

fbshipit-source-id: 05787ff
2017-01-19 13:39:12 -08:00
Dmitri Smirnov c70d3c7ade Enable DBTest.GroupCommit as it runs in a reasonlable time now.
Summary:
Remove ReRuns as they only waste time.
  Add env_basic_test to get more foundation coverage.
Closes https://github.com/facebook/rocksdb/pull/1788

Differential Revision: D4431433

Pulled By: IslamAbdelRahman

fbshipit-source-id: 50d07f8
2017-01-18 14:24:11 -08:00
Yi Wu 602c13a964 Remove fadvise with direct IO read
Summary:
Remove the logic since we don't use buffer cache with direct IO. Resolve
read regression we currently have.
Closes https://github.com/facebook/rocksdb/pull/1782

Differential Revision: D4430408

Pulled By: yiwu-arbug

fbshipit-source-id: 5557bba
2017-01-18 12:09:10 -08:00
Andrew Kryczka f9d18e22d2 Fix DeleteRange file boundary correctness issue with max_compaction_bytes
Summary:
Cockroachdb exposed this bug in #1778. The bug happens when a compaction's output files are ended due to exceeding max_compaction_bytes. In that case we weren't taking into account the next file's start key when deciding how far to extend the current file's max_key. This caused the non-overlapping key-range invariant to be violated.

Note this was correctly handled for the usual case of cutting compaction output, which is file size exceeding max_output_file_size. I am not sure why these are two separate code paths, but we can consider refactoring it to prevent such errors in the future.
Closes https://github.com/facebook/rocksdb/pull/1784

Differential Revision: D4430235

Pulled By: ajkr

fbshipit-source-id: 80af748
2017-01-18 11:54:22 -08:00
Islam AbdelRahman 3ce091fd73 Add KEEP_DB env var option
Summary:
When debugging tests, it's useful to preserve the DB to investigate it and check the logs
This will allow us to set KEEP_DB=1 to preserve the DB
Closes https://github.com/facebook/rocksdb/pull/1759

Differential Revision: D4393826

Pulled By: IslamAbdelRahman

fbshipit-source-id: 1bff689
2017-01-17 13:54:20 -08:00
Siying Dong 77b4806625 Fix 2PC with concurrent memtable insert
Summary:
If concurrent memtable insert is enabled, and one prepare command and a normal command are grouped into a commit group, the sequence ID will be calculated incorrectly.
Closes https://github.com/facebook/rocksdb/pull/1730

Differential Revision: D4371081

Pulled By: siying

fbshipit-source-id: cd40c6d
2017-01-17 11:24:28 -08:00
Kefu Chai e8a096000b util/thread_local.h: silence a clang-build warning
Summary:
otherwise clang complains with

/home/jenkins/workspace/ceph-master/src/rocksdb/util/thread_local.h:205:5:
error: macro expansion producing 'defined' has undefined behavior
[-Werror,-Wexpansion-to-defined]
^
/home/jenkins/workspace/ceph-master/src/rocksdb/util/thread_local.h:22:4:
note: expanded from macro 'ROCKSDB_SUPPORT_THREAD_LOCAL'
!defined(OS_WIN) && !defined(OS_MACOSX) && !defined(IOS_CROSS_COMPILE)
^`

Signed-off-by: Kefu Chai <tchaikov@gmail.com>
Closes https://github.com/facebook/rocksdb/pull/1757

Differential Revision: D4394140

Pulled By: siying

fbshipit-source-id: f0beda0
2017-01-15 13:24:16 -08:00
Dmitri Smirnov 324a0f988e Follow up for DirectIO refactor
Summary: Windows follow up for  https://github.com/facebook/rocksdb/commit/dc2584eea0d9965f97d38d4d462a7b57750144d3

Differential Revision: D4420337

Pulled By: IslamAbdelRahman

fbshipit-source-id: fedc5b5
2017-01-15 13:24:16 -08:00
145 changed files with 3364 additions and 1413 deletions

No files matched your search

+4 -2
View File
@@ -20,8 +20,10 @@ addons:
env:
# Run all tests before db_block_cache_test (db_test, db_test2)
- JOB_NAME=unittests ROCKSDBTESTS_END=db_block_cache_test
# Run all tests starting from db_block_cache_test (db_block_cache_test, db_iter_test, ...)
- JOB_NAME=unittests ROCKSDBTESTS_START=db_block_cache_test
# Run all tests starting from db_block_cache_test (db_block_cache_test, ..., plain_table_db_test)
- JOB_NAME=unittests ROCKSDBTESTS_START=db_block_cache_test ROCKSDBTESTS_END=comparator_db_test
# Run all tests starting from db_block_cache_test (comparator_db_test, ...)
- JOB_NAME=unittests ROCKSDBTESTS_START=comparator_db_test
# Run java tests
- JOB_NAME=java_test
# Build ROCKSDB_LITE
+82 -28
View File
@@ -1,4 +1,5 @@
# This cmake build is for Windows 64-bit only.
# Prerequisites for Windows:
# This cmake build is for Windows 64-bit only.
#
# Prerequisites:
# You must have at least Visual Studio 2015 Update 3. Start the Developer Command Prompt window that is a part of Visual Studio installation.
@@ -24,6 +25,12 @@
# 5. And release mode (/m[:<N>] is also supported)
# msbuild rocksdb.sln /p:Configuration=Release
#
# Linux:
#
# 1. Install a recent toolchain such as devtoolset-3 if you're on a older distro. C++11 required.
# 2. mkdir build; cd build
# 3. cmake ..
# 4. make -j
cmake_minimum_required(VERSION 2.6)
project(rocksdb)
@@ -83,6 +90,21 @@ endif()
string(REGEX REPLACE "[^0-9a-f]+" "" GIT_SHA "${GIT_SHA}")
if (NOT WIN32)
execute_process(COMMAND
"./build_tools/version.sh" "full"
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE ROCKSDB_VERSION
)
string(STRIP "${ROCKSDB_VERSION}" ROCKSDB_VERSION)
execute_process(COMMAND
"./build_tools/version.sh" "major"
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE ROCKSDB_VERSION_MAJOR
)
string(STRIP "${ROCKSDB_VERSION_MAJOR}" ROCKSDB_VERSION_MAJOR)
endif()
set(BUILD_VERSION_CC ${CMAKE_BINARY_DIR}/build_version.cc)
configure_file(util/build_version.cc.in ${BUILD_VERSION_CC} @ONLY)
add_library(build_version OBJECT ${BUILD_VERSION_CC})
@@ -96,7 +118,14 @@ else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -W -Wextra -Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsign-compare -Wshadow -Wno-unused-parameter -Wno-unused-variable -Woverloaded-virtual -Wnon-virtual-dtor -Wno-missing-field-initializers")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer -momit-leaf-frame-pointer")
if(NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-omit-frame-pointer")
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-momit-leaf-frame-pointer" HAVE_OMIT_LEAF_FRAME_POINTER)
if(HAVE_OMIT_LEAF_FRAME_POINTER)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -momit-leaf-frame-pointer")
endif()
endif()
endif()
option(FAIL_ON_WARNINGS "Treat compile warnings as errors" ON)
@@ -229,19 +258,9 @@ endif()
include_directories(${PROJECT_SOURCE_DIR})
include_directories(${PROJECT_SOURCE_DIR}/include)
include_directories(SYSTEM ${PROJECT_SOURCE_DIR}/third-party/gtest-1.7.0/fused-src)
find_package(Threads REQUIRED)
if(WIN32)
set(SYSTEM_LIBS ${SYSTEM_LIBS} Shlwapi.lib Rpcrt4.lib)
else()
set(SYSTEM_LIBS ${CMAKE_THREAD_LIBS_INIT})
endif()
set(ROCKSDB_LIBS rocksdblib${ARTIFACT_SUFFIX})
set(LIBS ${ROCKSDB_LIBS} ${THIRDPARTY_LIBS} ${SYSTEM_LIBS})
add_subdirectory(third-party/gtest-1.7.0/fused-src/gtest)
add_subdirectory(tools)
# Main library source code
@@ -319,7 +338,7 @@ set(SOURCES
table/full_filter_block.cc
table/get_context.cc
table/iterator.cc
table/merger.cc
table/merging_iterator.cc
table/sst_file_writer.cc
table/meta_blocks.cc
table/plain_table_builder.cc
@@ -358,6 +377,7 @@ set(SOURCES
util/histogram_windowing.cc
util/instrumented_mutex.cc
util/iostats_context.cc
util/lru_cache.cc
tools/ldb_cmd.cc
tools/ldb_tool.cc
@@ -399,7 +419,6 @@ set(SOURCES
utilities/document/json_document.cc
utilities/document/json_document_builder.cc
utilities/env_mirror.cc
utilities/env_registry.cc
utilities/geodb/geodb_impl.cc
utilities/leveldb_options/leveldb_options.cc
utilities/lua/rocks_lua_compaction_filter.cc
@@ -443,6 +462,7 @@ if(WIN32)
port/win/env_default.cc
port/win/port_win.cc
port/win/win_logger.cc
port/win/win_thread.cc
port/win/xpress_win.cc)
else()
list(APPEND SOURCES
@@ -451,6 +471,29 @@ else()
util/io_posix.cc)
endif()
if(WIN32)
set(SYSTEM_LIBS ${SYSTEM_LIBS} Shlwapi.lib Rpcrt4.lib)
set(ROCKSDB_STATIC_LIB rocksdblib${ARTIFACT_SUFFIX})
set(ROCKSDB_IMPORT_LIB rocksdb${ARTIFACT_SUFFIX})
set(LIBS ${ROCKSDB_STATIC_LIB} ${THIRDPARTY_LIBS} ${SYSTEM_LIBS})
else()
set(SYSTEM_LIBS ${CMAKE_THREAD_LIBS_INIT} rt)
set(ROCKSDB_STATIC_LIB rocksdb${ARTIFACT_SUFFIX})
set(ROCKSDB_SHARED_LIB rocksdb-shared)
set(ROCKSDB_IMPORT_LIB ${ROCKSDB_SHARED_LIB})
set(LIBS ${ROCKSDB_SHARED_LIB} ${THIRDPARTY_LIBS} ${SYSTEM_LIBS})
add_library(${ROCKSDB_SHARED_LIB} SHARED ${SOURCES})
target_link_libraries(${ROCKSDB_SHARED_LIB}
${THIRDPARTY_LIBS} ${SYSTEM_LIBS})
set_target_properties(${ROCKSDB_SHARED_LIB} PROPERTIES
LINKER_LANGUAGE CXX
VERSION ${ROCKSDB_VERSION}
SOVERSION ${ROCKSDB_VERSION_MAJOR}
CXX_STANDARD 11
OUTPUT_NAME "rocksdb")
endif()
option(WITH_LIBRADOS "Build with librados" OFF)
if(WITH_LIBRADOS)
list(APPEND SOURCES
@@ -458,22 +501,22 @@ if(WITH_LIBRADOS)
list(APPEND THIRDPARTY_LIBS rados)
endif()
add_library(rocksdblib${ARTIFACT_SUFFIX} STATIC ${SOURCES})
target_link_libraries(rocksdblib${ARTIFACT_SUFFIX}
add_library(${ROCKSDB_STATIC_LIB} STATIC ${SOURCES})
target_link_libraries(${ROCKSDB_STATIC_LIB}
${THIRDPARTY_LIBS} ${SYSTEM_LIBS})
if(WIN32)
set_target_properties(rocksdblib${ARTIFACT_SUFFIX} PROPERTIES
COMPILE_FLAGS "/Fd${CMAKE_CFG_INTDIR}/rocksdblib${ARTIFACT_SUFFIX}.pdb")
set_target_properties(${ROCKSDB_STATIC_LIB} PROPERTIES
COMPILE_FLAGS "/Fd${CMAKE_CFG_INTDIR}/${ROCKSDB_STATIC_LIB}.pdb")
endif()
add_library(rocksdb${ARTIFACT_SUFFIX} SHARED ${SOURCES})
target_link_libraries(rocksdb${ARTIFACT_SUFFIX}
${THIRDPARTY_LIBS} ${SYSTEM_LIBS})
if(WIN32)
set_target_properties(rocksdb${ARTIFACT_SUFFIX} PROPERTIES
COMPILE_FLAGS "-DROCKSDB_DLL -DROCKSDB_LIBRARY_EXPORTS /Fd${CMAKE_CFG_INTDIR}/rocksdb${ARTIFACT_SUFFIX}.pdb")
add_library(${ROCKSDB_IMPORT_LIB} SHARED ${SOURCES})
target_link_libraries(${ROCKSDB_IMPORT_LIB}
${THIRDPARTY_LIBS} ${SYSTEM_LIBS})
set_target_properties(${ROCKSDB_IMPORT_LIB} PROPERTIES
COMPILE_FLAGS "-DROCKSDB_DLL -DROCKSDB_LIBRARY_EXPORTS /Fd${CMAKE_CFG_INTDIR}/${ROCKSDB_IMPORT_LIB}.pdb")
else()
endif()
option(WITH_JNI "build with JNI" OFF)
@@ -587,7 +630,7 @@ set(TESTS
utilities/date_tiered/date_tiered_test.cc
utilities/document/document_db_test.cc
utilities/document/json_document_test.cc
utilities/env_registry_test.cc
utilities/object_registry_test.cc
utilities/geodb/geodb_test.cc
utilities/memory/memory_test.cc
utilities/merge_operators/string_append/stringappend_test.cc
@@ -621,7 +664,7 @@ foreach(sourcefile ${BENCHMARKS})
get_filename_component(exename ${sourcefile} NAME_WE)
add_executable(${exename}${ARTIFACT_SUFFIX} ${sourcefile}
$<TARGET_OBJECTS:testharness>)
target_link_libraries(${exename}${ARTIFACT_SUFFIX} ${LIBS} gtest)
target_link_libraries(${exename}${ARTIFACT_SUFFIX} gtest ${LIBS})
endforeach(sourcefile ${BENCHMARKS})
# For test util library that is build only in DEBUG mode
@@ -659,7 +702,7 @@ foreach(sourcefile ${TEST_EXES})
EXCLUDE_FROM_DEFAULT_BUILD_MINRELEASE 1
EXCLUDE_FROM_DEFAULT_BUILD_RELWITHDEBINFO 1
)
target_link_libraries(${exename}${ARTIFACT_SUFFIX} testutillib${ARTIFACT_SUFFIX} ${LIBS} gtest)
target_link_libraries(${exename}${ARTIFACT_SUFFIX} testutillib${ARTIFACT_SUFFIX} gtest ${LIBS})
if(NOT "${exename}" MATCHES "db_sanity_test")
add_test(NAME ${exename} COMMAND ${exename}${ARTIFACT_SUFFIX})
add_dependencies(check ${exename}${ARTIFACT_SUFFIX})
@@ -679,7 +722,18 @@ foreach(sourcefile ${C_TEST_EXES})
EXCLUDE_FROM_DEFAULT_BUILD_MINRELEASE 1
EXCLUDE_FROM_DEFAULT_BUILD_RELWITHDEBINFO 1
)
target_link_libraries(${exename}${ARTIFACT_SUFFIX} rocksdb${ARTIFACT_SUFFIX} testutillib${ARTIFACT_SUFFIX})
target_link_libraries(${exename}${ARTIFACT_SUFFIX} ${ROCKSDB_IMPORT_LIB} testutillib${ARTIFACT_SUFFIX})
add_test(NAME ${exename} COMMAND ${exename}${ARTIFACT_SUFFIX})
add_dependencies(check ${exename}${ARTIFACT_SUFFIX})
endforeach(sourcefile ${C_TEST_EXES})
add_subdirectory(tools)
# Installation and packaging for Linux
if (NOT WIN32)
install(TARGETS ${ROCKSDB_STATIC_LIB} COMPONENT devel ARCHIVE DESTINATION lib64)
install(TARGETS ${ROCKSDB_SHARED_LIB} COMPONENT runtime DESTINATION lib64)
install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/rocksdb/"
COMPONENT devel
DESTINATION include/rocksdb)
set(CMAKE_INSTALL_PREFIX /usr)
endif()
+7
View File
@@ -1,4 +1,11 @@
# RocksDB default options change log
## Unreleased
* Change the default of delayed slowdown value to 16MB/s and further increase the L0 stop condition to 36 files.
## 5.0 (11/17/2016)
* Options::allow_concurrent_memtable_write and Options::enable_write_thread_adaptive_yield are now true by default
* Options.level0_stop_writes_trigger default value changes from 24 to 32.
## 4.8.0 (5/2/2016)
* options.max_open_files changes from 5000 to -1. It improves performance, but users need to set file descriptor limit to be large enough and watch memory usage for index and bloom filters.
* options.base_background_compactions changes from max_background_compactions to 1. When users set higher max_background_compactions but the write throughput is not high, the writes are less spiky to disks.
+17
View File
@@ -1,6 +1,23 @@
# Rocksdb Change Log
## Unreleased
## 5.2.0 (02/08/2017)
### Public API Change
* NewLRUCache() will determine number of shard bits automatically based on capacity, if the user doesn't pass one. This also impacts the default block cache when the user doesn't explict provide one.
* Change the default of delayed slowdown value to 16MB/s and further increase the L0 stop condition to 36 files.
* (Experimental) Two-level indexing that partition the index and creates a 2nd level index on the partitions. The feature can be enabled by setting kTwoLevelIndexSearch as IndexType and configuring index_per_partition.
### New Features
* Added new overloaded function GetApproximateSizes that allows to specify if memtable stats should be computed only without computing SST files' stats approximations.
* Added new function GetApproximateMemTableStats that approximates both number of records and size of memtables.
### Bug Fixes
* RangeSync() should work if ROCKSDB_FALLOCATE_PRESENT is not set
* Fix wrong results in a data race case in Get()
* Some fixes related to 2PC.
* Fix several bugs in Direct I/O supports.
## 5.1.0 (01/13/2017)
* Support dynamically change `delete_obsolete_files_period_micros` option via SetDBOptions().
* Added EventListener::OnExternalFileIngested which will be called when IngestExternalFile() add a file successfully.
* BackupEngine::Open and BackupEngineReadOnly::Open now always return error statuses matching those of the backup Env.
+8 -12
View File
@@ -223,11 +223,6 @@ default: all
WARNING_FLAGS = -W -Wextra -Wall -Wsign-compare -Wshadow \
-Wno-unused-parameter
ifndef DISABLE_WARNING_AS_ERROR
WARNING_FLAGS += -Werror
endif
ifdef LUA_PATH
ifndef LUA_INCLUDE
@@ -421,6 +416,7 @@ TESTS = \
lua_test \
range_del_aggregator_test \
lru_cache_test \
object_registry_test \
PARALLEL_TEST = \
backupable_db_test \
@@ -1085,7 +1081,7 @@ env_librados_test: utilities/env_librados_test.o $(LIBOBJECTS) $(TESTHARNESS)
$(AM_V_CCLD)$(CXX) $^ $(EXEC_LDFLAGS) -o $@ $(LDFLAGS) $(COVERAGEFLAGS)
endif
env_registry_test: utilities/env_registry_test.o $(LIBOBJECTS) $(TESTHARNESS)
object_registry_test: utilities/object_registry_test.o $(LIBOBJECTS) $(TESTHARNESS)
$(AM_LINK)
ttl_test: utilities/ttl/ttl_test.o $(LIBOBJECTS) $(TESTHARNESS)
@@ -1390,11 +1386,11 @@ ifeq ($(PLATFORM), OS_SOLARIS)
endif
libz.a:
-rm -rf zlib-1.2.8
curl -O -L http://zlib.net/zlib-1.2.8.tar.gz
tar xvzf zlib-1.2.8.tar.gz
cd zlib-1.2.8 && CFLAGS='-fPIC' ./configure --static && make
cp zlib-1.2.8/libz.a .
-rm -rf zlib-1.2.10
curl -O -L http://zlib.net/zlib-1.2.10.tar.gz
tar xvzf zlib-1.2.10.tar.gz
cd zlib-1.2.10 && CFLAGS='-fPIC' ./configure --static && make
cp zlib-1.2.10/libz.a .
libbz2.a:
-rm -rf bzip2-1.0.6
@@ -1424,7 +1420,7 @@ java_static_libobjects = $(patsubst %,jls/%,$(LIBOBJECTS))
CLEAN_FILES += jls
JAVA_STATIC_FLAGS = -DZLIB -DBZIP2 -DSNAPPY -DLZ4
JAVA_STATIC_INCLUDES = -I./zlib-1.2.8 -I./bzip2-1.0.6 -I./snappy-1.1.3 -I./lz4-r127/lib
JAVA_STATIC_INCLUDES = -I./zlib-1.2.10 -I./bzip2-1.0.6 -I./snappy-1.1.3 -I./lz4-r127/lib
$(java_static_libobjects): jls/%.o: %.cc libz.a libbz2.a libsnappy.a liblz4.a
$(AM_V_CC)mkdir -p $(@D) && $(CXX) $(CXXFLAGS) $(JAVA_STATIC_FLAGS) $(JAVA_STATIC_INCLUDES) -fPIC -c $< -o $@ $(COVERAGEFLAGS)
+3
View File
@@ -77,3 +77,6 @@ quasardb uses a heavily tuned RocksDB as its persistence layer.
## Uber
[Uber](http://eng.uber.com/cherami/) uses RocksDB as a durable and and scalable task queue.
## 360 Pika
[360](http://www.360.cn/) [Pika](https://github.com/Qihoo360/pika) is a nosql compatible with redis. With the huge amount of data stored, redis may suffer for a capacity bottleneck, and pika was born for solving it. It has widely been widely used in many company
+3 -3
View File
@@ -11,7 +11,7 @@ build:
verbosity: minimal
test:
test_script:
- ps: build_tools\run_ci_db_test.ps1 -EnableRerun -Run db_test2 -Concurrency 8
- ps: build_tools\run_ci_db_test.ps1 -EnableRerun -Run db_test -Exclude DBTest.GroupCommitTest -Concurrency 10
- ps: build_tools\run_ci_db_test.ps1 -Run env_test -Concurrency 1
- ps: build_tools\run_ci_db_test.ps1 -Run db_test2 -Concurrency 8
- ps: build_tools\run_ci_db_test.ps1 -Run db_test -Concurrency 8
- ps: build_tools\run_ci_db_test.ps1 -Run env_test,env_basic_test -Concurrency 2
@@ -9,6 +9,13 @@ require('RocksDBCommonHelper.php');
define("DIFF_COMMAND", "diff");
class FacebookArcanistConfiguration extends ArcanistConfiguration {
public function getCustomArgumentsForCommand($command) {
if ($command == "land") {
return array(
'async' => array('help' => 'Just to make tools happy'));
}
return array();
}
public function didRunWorkflow($command,
ArcanistWorkflow $workflow,
@@ -9,6 +9,13 @@ require('RocksDBCommonHelper.php');
define("DIFF_COMMAND", "diff");
class FacebookArcanistConfiguration extends ArcanistConfiguration {
public function getCustomArgumentsForCommand($command) {
if ($command == "land") {
return array(
'async' => array('help' => 'Just to make tools happy'));
}
return array();
}
public function didRunWorkflow($command,
ArcanistBaseWorkflow $workflow,
+1 -6
View File
@@ -51,12 +51,7 @@ if [ -z "$ROCKSDB_NO_FBCODE" -a -d /mnt/gvfs/third-party ]; then
FBCODE_BUILD="true"
# If we're compiling with TSAN we need pic build
PIC_BUILD=$COMPILE_WITH_TSAN
if [ -z "$ROCKSDB_FBCODE_BUILD_WITH_481" ]; then
source "$PWD/build_tools/fbcode_config.sh"
else
# we need this to build with MySQL. Don't use for other purposes.
source "$PWD/build_tools/fbcode_config4.8.1.sh"
fi
source "$PWD/build_tools/fbcode_config.sh"
fi
# Delete existing output, if it exists
+19 -18
View File
@@ -1,18 +1,19 @@
GCC_BASE=/mnt/gvfs/third-party2/gcc/cf7d14c625ce30bae1a4661c2319c5a283e4dd22/4.9.x/centos6-native/108cf83
CLANG_BASE=/mnt/gvfs/third-party2/llvm-fb/8598c375b0e94e1448182eb3df034704144a838d/stable/centos6-native/3f16ddd
LIBGCC_BASE=/mnt/gvfs/third-party2/libgcc/d6e0a7da6faba45f5e5b1638f9edd7afc2f34e7d/4.9.x/gcc-4.9-glibc-2.20/024dbc3
GLIBC_BASE=/mnt/gvfs/third-party2/glibc/d282e6e8f3d20f4e40a516834847bdc038e07973/2.20/gcc-4.9-glibc-2.20/500e281
SNAPPY_BASE=/mnt/gvfs/third-party2/snappy/8c38a4c1e52b4c2cc8a9cdc31b9c947ed7dbfcb4/1.1.3/gcc-4.9-glibc-2.20/e9936bf
ZLIB_BASE=/mnt/gvfs/third-party2/zlib/0882df3713c7a84f15abe368dc004581f20b39d7/1.2.8/gcc-5-glibc-2.23/9bc6787
BZIP2_BASE=/mnt/gvfs/third-party2/bzip2/740325875f6729f42d28deaa2147b0854f3a347e/1.0.6/gcc-5-glibc-2.23/9bc6787
LZ4_BASE=/mnt/gvfs/third-party2/lz4/0e790b441e2d9acd68d51e1d2e028f88c6a79ddf/r131/gcc-5-glibc-2.23/9bc6787
ZSTD_BASE=/mnt/gvfs/third-party2/zstd/9455f75ff7f4831dc9fda02a6a0f8c68922fad8f/1.0.0/gcc-5-glibc-2.23/9bc6787
GFLAGS_BASE=/mnt/gvfs/third-party2/gflags/f001a51b2854957676d07306ef3abf67186b5c8b/2.1.1/gcc-4.8.1-glibc-2.17/c3f970a
JEMALLOC_BASE=/mnt/gvfs/third-party2/jemalloc/fc8a13ca1fffa4d0765c716c5a0b49f0c107518f/master/gcc-5-glibc-2.23/1c32b4b
NUMA_BASE=/mnt/gvfs/third-party2/numa/17c514c4d102a25ca15f4558be564eeed76f4b6a/2.0.8/gcc-5-glibc-2.23/9bc6787
LIBUNWIND_BASE=/mnt/gvfs/third-party2/libunwind/ad576de2a1ea560c4d3434304f0fc4e079bede42/trunk/gcc-5-glibc-2.23/b1847cb
TBB_BASE=/mnt/gvfs/third-party2/tbb/9d9a554877d0c5bef330fe818ab7178806dd316a/4.0_update2/gcc-4.9-glibc-2.20/e9936bf
KERNEL_HEADERS_BASE=/mnt/gvfs/third-party2/kernel-headers/7c111ff27e0c466235163f00f280a9d617c3d2ec/4.0.9-36_fbk5_2933_gd092e3f/gcc-5-glibc-2.23/da39a3e
BINUTILS_BASE=/mnt/gvfs/third-party2/binutils/b7fd454c4b10c6a81015d4524ed06cdeab558490/2.26/centos6-native/da39a3e
VALGRIND_BASE=/mnt/gvfs/third-party2/valgrind/d7f4d4d86674a57668e3a96f76f0e17dd0eb8765/3.10.0/gcc-4.9-glibc-2.20/e9936bf
LUA_BASE=/mnt/gvfs/third-party2/lua/61e4abf5813bbc39bc4f548757ccfcadde175a48/5.2.3/gcc-4.9-glibc-2.20/690f0d7
# Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
GCC_BASE=/mnt/gvfs/third-party2/gcc/7331085db891a2ef4a88a48a751d834e8d68f4cb/7.x/centos7-native/b2ef2b6
CLANG_BASE=/mnt/gvfs/third-party2/llvm-fb/963d9aeda70cc4779885b1277484fe7544a04e3e/9.0.0/platform007/9e92d53/
LIBGCC_BASE=/mnt/gvfs/third-party2/libgcc/6ace84e956873d53638c738b6f65f3f469cca74c/7.x/platform007/5620abc
GLIBC_BASE=/mnt/gvfs/third-party2/glibc/192b0f42d63dcf6210d6ceae387b49af049e6e0c/2.26/platform007/f259413
SNAPPY_BASE=/mnt/gvfs/third-party2/snappy/7f9bdaada18f59bc27ec2b0871eb8a6144343aef/1.1.3/platform007/ca4da3d
ZLIB_BASE=/mnt/gvfs/third-party2/zlib/2d9f0b9a4274cc21f61272a9e89bdb859bce8f1f/1.2.8/platform007/ca4da3d
BZIP2_BASE=/mnt/gvfs/third-party2/bzip2/dc49a21c5fceec6456a7a28a94dcd16690af1337/1.0.6/platform007/ca4da3d
LZ4_BASE=/mnt/gvfs/third-party2/lz4/0f607f8fc442ea7d6b876931b1898bb573d5e5da/1.9.1/platform007/ca4da3d
ZSTD_BASE=/mnt/gvfs/third-party2/zstd/ca22bc441a4eb709e9e0b1f9fec9750fed7b31c5/1.4.x/platform007/15a3614
GFLAGS_BASE=/mnt/gvfs/third-party2/gflags/0b9929d2588991c65a57168bf88aff2db87c5d48/2.2.0/platform007/ca4da3d
JEMALLOC_BASE=/mnt/gvfs/third-party2/jemalloc/c26f08f47ac35fc31da2633b7da92d6b863246eb/master/platform007/c26c002
NUMA_BASE=/mnt/gvfs/third-party2/numa/3f3fb57a5ccc5fd21c66416c0b83e0aa76a05376/2.0.11/platform007/ca4da3d
LIBUNWIND_BASE=/mnt/gvfs/third-party2/libunwind/40c73d874898b386a71847f1b99115d93822d11f/1.4/platform007/6f3e0a9
TBB_BASE=/mnt/gvfs/third-party2/tbb/4ce8e8dba77cdbd81b75d6f0c32fd7a1b76a11ec/2018_U5/platform007/ca4da3d
KERNEL_HEADERS_BASE=/mnt/gvfs/third-party2/kernel-headers/fb251ecd2f5ae16f8671f7014c246e52a748fe0b/fb/platform007/da39a3e
BINUTILS_BASE=/mnt/gvfs/third-party2/binutils/ab9f09bba370e7066cafd4eb59752db93f2e8312/2.29.1/platform007/15a3614
VALGRIND_BASE=/mnt/gvfs/third-party2/valgrind/d42d152a15636529b0861ec493927200ebebca8e/3.15.0/platform007/ca4da3d
LUA_BASE=/mnt/gvfs/third-party2/lua/f0cd714433206d5139df61659eb7b28b1dea6683/5.3.4/platform007/5007832
+18 -21
View File
@@ -13,7 +13,7 @@ source "$BASEDIR/dependencies.sh"
CFLAGS=""
# libgcc
LIBGCC_INCLUDE="$LIBGCC_BASE/include"
LIBGCC_INCLUDE="$LIBGCC_BASE/include/c++/7.3.0"
LIBGCC_LIBS=" -L $LIBGCC_BASE/lib"
# glibc
@@ -43,12 +43,16 @@ if test -z $PIC_BUILD; then
LZ4_INCLUDE=" -I $LZ4_BASE/include/"
LZ4_LIBS=" $LZ4_BASE/lib/liblz4.a"
CFLAGS+=" -DLZ4"
ZSTD_INCLUDE=" -I $ZSTD_BASE/include/"
ZSTD_LIBS=" $ZSTD_BASE/lib/libzstd.a"
CFLAGS+=" -DZSTD"
fi
ZSTD_INCLUDE=" -I $ZSTD_BASE/include/"
if test -z $PIC_BUILD; then
ZSTD_LIBS=" $ZSTD_BASE/lib/libzstd.a"
else
ZSTD_LIBS=" $ZSTD_BASE/lib/libzstd_pic.a"
fi
CFLAGS+=" -DZSTD"
# location of gflags headers and libraries
GFLAGS_INCLUDE=" -I $GFLAGS_BASE/include/"
if test -z $PIC_BUILD; then
@@ -56,7 +60,7 @@ if test -z $PIC_BUILD; then
else
GFLAGS_LIBS=" $GFLAGS_BASE/lib/libgflags_pic.a"
fi
CFLAGS+=" -DGFLAGS=google"
CFLAGS+=" -DGFLAGS=gflags"
# location of jemalloc
JEMALLOC_INCLUDE=" -I $JEMALLOC_BASE/include/"
@@ -104,8 +108,8 @@ if [ -z "$USE_CLANG" ]; then
CXX="$GCC_BASE/bin/g++"
CFLAGS+=" -B$BINUTILS/gold"
CFLAGS+=" -isystem $GLIBC_INCLUDE"
CFLAGS+=" -isystem $LIBGCC_INCLUDE"
CFLAGS+=" -isystem $GLIBC_INCLUDE"
JEMALLOC=1
else
# clang
@@ -116,8 +120,8 @@ else
KERNEL_HEADERS_INCLUDE="$KERNEL_HEADERS_BASE/include"
CFLAGS+=" -B$BINUTILS/gold -nostdinc -nostdlib"
CFLAGS+=" -isystem $LIBGCC_BASE/include/c++/4.9.x "
CFLAGS+=" -isystem $LIBGCC_BASE/include/c++/4.9.x/x86_64-facebook-linux "
CFLAGS+=" -isystem $LIBGCC_BASE/include/c++/7.x "
CFLAGS+=" -isystem $LIBGCC_BASE/include/c++/7.x/x86_64-facebook-linux "
CFLAGS+=" -isystem $GLIBC_INCLUDE"
CFLAGS+=" -isystem $LIBGCC_INCLUDE"
CFLAGS+=" -isystem $CLANG_INCLUDE"
@@ -128,13 +132,14 @@ else
fi
CFLAGS+=" $DEPS_INCLUDE"
CFLAGS+=" -DROCKSDB_PLATFORM_POSIX -DROCKSDB_LIB_IO_POSIX -DROCKSDB_FALLOCATE_PRESENT -DROCKSDB_MALLOC_USABLE_SIZE"
CFLAGS+=" -DROCKSDB_PLATFORM_POSIX -DROCKSDB_LIB_IO_POSIX -DROCKSDB_FALLOCATE_PRESENT -DROCKSDB_MALLOC_USABLE_SIZE -DROCKSDB_RANGESYNC_PRESENT -DROCKSDB_SCHED_GETCPU_PRESENT -DROCKSDB_SUPPORT_THREAD_LOCAL -DHAVE_SSE42"
CXXFLAGS+=" $CFLAGS"
EXEC_LDFLAGS=" $SNAPPY_LIBS $ZLIB_LIBS $BZIP_LIBS $LZ4_LIBS $ZSTD_LIBS $GFLAGS_LIBS $NUMA_LIB $TBB_LIBS"
EXEC_LDFLAGS+=" -Wl,--dynamic-linker,/usr/local/fbcode/gcc-4.9-glibc-2.20/lib/ld.so"
EXEC_LDFLAGS+=" -B$BINUTILS/gold"
EXEC_LDFLAGS+=" -Wl,--dynamic-linker,/usr/local/fbcode/platform007/lib/ld.so"
EXEC_LDFLAGS+=" $LIBUNWIND"
EXEC_LDFLAGS+=" -Wl,-rpath=/usr/local/fbcode/gcc-4.9-glibc-2.20/lib"
EXEC_LDFLAGS+=" -Wl,-rpath=/usr/local/fbcode/platform007/lib"
# required by libtbb
EXEC_LDFLAGS+=" -ldl"
@@ -144,12 +149,4 @@ EXEC_LDFLAGS_SHARED="$SNAPPY_LIBS $ZLIB_LIBS $BZIP_LIBS $LZ4_LIBS $ZSTD_LIBS $GF
VALGRIND_VER="$VALGRIND_BASE/bin/"
LUA_PATH="$LUA_BASE"
if test -z $PIC_BUILD; then
LUA_LIB=" $LUA_PATH/lib/liblua.a"
else
LUA_LIB=" $LUA_PATH/lib/liblua_pic.a"
fi
export CC CXX AR CFLAGS CXXFLAGS EXEC_LDFLAGS EXEC_LDFLAGS_SHARED VALGRIND_VER JEMALLOC_LIB JEMALLOC_INCLUDE CLANG_ANALYZER CLANG_SCAN_BUILD LUA_PATH LUA_LIB
export CC CXX AR CFLAGS CXXFLAGS EXEC_LDFLAGS EXEC_LDFLAGS_SHARED VALGRIND_VER JEMALLOC_LIB JEMALLOC_INCLUDE CLANG_ANALYZER CLANG_SCAN_BUILD
+1 -1
View File
@@ -1,4 +1,4 @@
#!/usr/local/fbcode/gcc-4.8.1-glibc-2.17-fb/bin/python2.7
#!/usr/local/fbcode/gcc-4.9-glibc-2.20-fb/bin/python2.7
from __future__ import absolute_import
from __future__ import division
+9 -1
View File
@@ -1,8 +1,9 @@
#!/bin/sh
if [ "$#" = "0" ]; then
echo "Usage: $0 major|minor|patch"
echo "Usage: $0 major|minor|patch|full"
exit 1
fi
if [ "$1" = "major" ]; then
cat include/rocksdb/version.h | grep MAJOR | head -n1 | awk '{print $3}'
fi
@@ -12,3 +13,10 @@ fi
if [ "$1" = "patch" ]; then
cat include/rocksdb/version.h | grep PATCH | head -n1 | awk '{print $3}'
fi
if [ "$1" = "full" ]; then
awk '/#define ROCKSDB/ { env[$2] = $3 }
END { printf "%s.%s.%s\n", env["ROCKSDB_MAJOR"],
env["ROCKSDB_MINOR"],
env["ROCKSDB_PATCH"] }' \
include/rocksdb/version.h
fi
+2 -2
View File
@@ -271,7 +271,7 @@ TEST_F(AutoRollLoggerTest, LogFlushWhileRolling) {
AutoRollLogger* auto_roll_logger =
dynamic_cast<AutoRollLogger*>(logger.get());
ASSERT_TRUE(auto_roll_logger);
std::thread flush_thread;
rocksdb::port::Thread flush_thread;
// Notes:
// (1) Need to pin the old logger before beginning the roll, as rolling grabs
@@ -293,7 +293,7 @@ TEST_F(AutoRollLoggerTest, LogFlushWhileRolling) {
{"AutoRollLogger::Flush:PinnedLogger", "PosixLogger::Flush:Begin2"}});
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
flush_thread = std::thread([&]() { auto_roll_logger->Flush(); });
flush_thread = port::Thread ([&]() { auto_roll_logger->Flush(); });
TEST_SYNC_POINT(
"AutoRollLoggerTest::LogFlushWhileRolling:PreRollAndPostThreadInit");
RollLogFileBySizeTest(auto_roll_logger, options.max_log_file_size,
+40
View File
@@ -901,6 +901,17 @@ char* rocksdb_property_value(
}
}
int rocksdb_property_int(
rocksdb_t* db,
const char* propname,
uint64_t *out_val) {
if (db->rep->GetIntProperty(Slice(propname), out_val)) {
return 0;
} else {
return -1;
}
}
char* rocksdb_property_value_cf(
rocksdb_t* db,
rocksdb_column_family_handle_t* column_family,
@@ -1336,6 +1347,15 @@ const char* rocksdb_writebatch_data(rocksdb_writebatch_t* b, size_t* size) {
return b->rep.Data().c_str();
}
void rocksdb_writebatch_set_save_point(rocksdb_writebatch_t* b) {
b->rep.SetSavePoint();
}
void rocksdb_writebatch_rollback_to_save_point(rocksdb_writebatch_t* b,
char** errptr) {
SaveError(errptr, b->rep.RollbackToSavePoint());
}
rocksdb_block_based_table_options_t*
rocksdb_block_based_options_create() {
return new rocksdb_block_based_table_options_t;
@@ -1478,6 +1498,14 @@ void rocksdb_options_set_cuckoo_table_factory(
}
}
void rocksdb_set_options(
rocksdb_t* db, int count, const char* const keys[], const char* const values[], char** errptr) {
std::unordered_map<std::string, std::string> options_map;
for (int i=0; i<count; i++)
options_map[keys[i]] = values[i];
SaveError(errptr,
db->rep->SetOptions(options_map));
}
rocksdb_options_t* rocksdb_options_create() {
return new rocksdb_options_t;
@@ -1862,6 +1890,14 @@ void rocksdb_options_set_hard_rate_limit(rocksdb_options_t* opt, double v) {
opt->rep.hard_rate_limit = v;
}
void rocksdb_options_set_soft_pending_compaction_bytes_limit(rocksdb_options_t* opt, size_t v) {
opt->rep.soft_pending_compaction_bytes_limit = v;
}
void rocksdb_options_set_hard_pending_compaction_bytes_limit(rocksdb_options_t* opt, size_t v) {
opt->rep.hard_pending_compaction_bytes_limit = v;
}
void rocksdb_options_set_rate_limit_delay_max_milliseconds(
rocksdb_options_t* opt, unsigned int v) {
opt->rep.rate_limit_delay_max_milliseconds = v;
@@ -1891,6 +1927,10 @@ void rocksdb_options_set_disable_auto_compactions(rocksdb_options_t* opt, int di
opt->rep.disable_auto_compactions = disable;
}
void rocksdb_options_set_optimize_filters_for_hits(rocksdb_options_t* opt, int v) {
opt->rep.optimize_filters_for_hits = v;
}
void rocksdb_options_set_delete_obsolete_files_period_micros(
rocksdb_options_t* opt, uint64_t v) {
opt->rep.delete_obsolete_files_period_micros = v;
+17
View File
@@ -573,6 +573,23 @@ int main(int argc, char** argv) {
rocksdb_writebatch_destroy(wb);
}
StartPhase("writebatch_savepoint");
{
rocksdb_writebatch_t* wb = rocksdb_writebatch_create();
rocksdb_writebatch_set_save_point(wb);
const char* k_list[2] = {"z", "ap"};
const size_t k_sizes[2] = {1, 2};
const char* v_list[3] = {"x", "y", "z"};
const size_t v_sizes[3] = {1, 1, 1};
rocksdb_writebatch_putv(wb, 2, k_list, k_sizes, 3, v_list, v_sizes);
rocksdb_writebatch_rollback_to_save_point(wb, &err);
CheckNoError(err);
rocksdb_write(db, woptions, wb, &err);
CheckNoError(err);
CheckGet(db, roptions, "zap", NULL);
rocksdb_writebatch_destroy(wb);
}
StartPhase("writebatch_rep");
{
rocksdb_writebatch_t* wb1 = rocksdb_writebatch_create();
+21 -1
View File
@@ -370,7 +370,8 @@ ColumnFamilyData::ColumnFamilyData(
column_family_set_(column_family_set),
pending_flush_(false),
pending_compaction_(false),
prev_compaction_needed_bytes_(0) {
prev_compaction_needed_bytes_(0),
allow_2pc_(db_options.allow_2pc) {
Ref();
// Convert user defined table properties collector factories to internal ones.
@@ -492,6 +493,25 @@ ColumnFamilyOptions ColumnFamilyData::GetLatestCFOptions() const {
return BuildColumnFamilyOptions(initial_cf_options_, mutable_cf_options_);
}
uint64_t ColumnFamilyData::OldestLogToKeep() {
auto current_log = GetLogNumber();
if (allow_2pc_) {
auto imm_prep_log = imm()->GetMinLogContainingPrepSection();
auto mem_prep_log = mem()->GetMinLogContainingPrepSection();
if (imm_prep_log > 0 && imm_prep_log < current_log) {
current_log = imm_prep_log;
}
if (mem_prep_log > 0 && mem_prep_log < current_log) {
current_log = mem_prep_log;
}
}
return current_log;
}
const double kIncSlowdownRatio = 0.8;
const double kDecSlowdownRatio = 1 / kIncSlowdownRatio;
const double kNearStopSlowdownRatio = 0.6;
+6
View File
@@ -239,6 +239,9 @@ class ColumnFamilyData {
uint64_t GetTotalSstFilesSize() const; // REQUIRE: DB mutex held
void SetMemtable(MemTable* new_mem) { mem_ = new_mem; }
// calculate the oldest log needed for the durability of this column family
uint64_t OldestLogToKeep();
// See Memtable constructor for explanation of earliest_seq param.
MemTable* ConstructNewMemtable(const MutableCFOptions& mutable_cf_options,
SequenceNumber earliest_seq);
@@ -404,6 +407,9 @@ class ColumnFamilyData {
bool pending_compaction_;
uint64_t prev_compaction_needed_bytes_;
// if the database was opened with 2pc enabled
bool allow_2pc_;
};
// ColumnFamilySet has interesting thread-safety requirements
+12 -11
View File
@@ -15,6 +15,7 @@
#include "db/db_impl.h"
#include "db/db_test_util.h"
#include "port/port.h"
#include "rocksdb/db.h"
#include "rocksdb/env.h"
#include "rocksdb/iterator.h"
@@ -1268,7 +1269,7 @@ TEST_F(ColumnFamilyTest, MultipleManualCompactions) {
});
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
std::vector<std::thread> threads;
std::vector<port::Thread> threads;
threads.emplace_back([&] {
CompactRangeOptions compact_options;
compact_options.exclusive_manual_compaction = false;
@@ -1376,7 +1377,7 @@ TEST_F(ColumnFamilyTest, AutomaticAndManualCompactions) {
WaitForFlush(2);
AssertFilesPerLevel(ToString(i + 1), 2);
}
std::thread threads([&] {
rocksdb::port::Thread threads([&] {
CompactRangeOptions compact_options;
compact_options.exclusive_manual_compaction = false;
ASSERT_OK(
@@ -1464,7 +1465,7 @@ TEST_F(ColumnFamilyTest, ManualAndAutomaticCompactions) {
});
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
std::thread threads([&] {
rocksdb::port::Thread threads([&] {
CompactRangeOptions compact_options;
compact_options.exclusive_manual_compaction = false;
ASSERT_OK(
@@ -1557,7 +1558,7 @@ TEST_F(ColumnFamilyTest, SameCFManualManualCompactions) {
});
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
std::thread threads([&] {
rocksdb::port::Thread threads([&] {
CompactRangeOptions compact_options;
compact_options.exclusive_manual_compaction = true;
ASSERT_OK(
@@ -1577,7 +1578,7 @@ TEST_F(ColumnFamilyTest, SameCFManualManualCompactions) {
1);
}
std::thread threads1([&] {
rocksdb::port::Thread threads1([&] {
CompactRangeOptions compact_options;
compact_options.exclusive_manual_compaction = false;
ASSERT_OK(
@@ -1655,7 +1656,7 @@ TEST_F(ColumnFamilyTest, SameCFManualAutomaticCompactions) {
});
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
std::thread threads([&] {
rocksdb::port::Thread threads([&] {
CompactRangeOptions compact_options;
compact_options.exclusive_manual_compaction = false;
ASSERT_OK(
@@ -1747,7 +1748,7 @@ TEST_F(ColumnFamilyTest, SameCFManualAutomaticCompactionsLevel) {
});
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
std::thread threads([&] {
rocksdb::port::Thread threads([&] {
CompactRangeOptions compact_options;
compact_options.exclusive_manual_compaction = false;
ASSERT_OK(
@@ -1858,7 +1859,7 @@ TEST_F(ColumnFamilyTest, SameCFManualAutomaticConflict) {
});
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
std::thread threads([&] {
rocksdb::port::Thread threads([&] {
CompactRangeOptions compact_options;
compact_options.exclusive_manual_compaction = false;
ASSERT_OK(
@@ -2323,7 +2324,7 @@ TEST_F(ColumnFamilyTest, FlushAndDropRaceCondition) {
int kKeysNum = 10000;
PutRandomData(1, kKeysNum, 100);
std::vector<std::thread> threads;
std::vector<port::Thread> threads;
threads.emplace_back([&] { ASSERT_OK(db_->DropColumnFamily(handles_[1])); });
sleeping_task.WakeUp();
@@ -2424,7 +2425,7 @@ TEST_F(ColumnFamilyTest, CreateAndDropRace) {
// Start a thread that will drop the first column family
// and its comparator
std::thread drop_cf_thread(DropSingleColumnFamily, this, 1, &comparators);
rocksdb::port::Thread drop_cf_thread(DropSingleColumnFamily, this, 1, &comparators);
DropColumnFamilies({2});
@@ -3078,7 +3079,7 @@ TEST_F(ColumnFamilyTest, LogSyncConflictFlush) {
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
std::thread thread([&] { db_->SyncWAL(); });
rocksdb::port::Thread thread([&] { db_->SyncWAL(); });
TEST_SYNC_POINT("ColumnFamilyTest::LogSyncConflictFlush:1");
Flush(1);
+57 -1
View File
@@ -11,6 +11,7 @@
#include <vector>
#include "db/db_impl.h"
#include "port/port.h"
#include "rocksdb/db.h"
#include "rocksdb/env.h"
#include "util/string_util.h"
@@ -231,7 +232,7 @@ TEST_F(CompactFilesTest, CapturingPendingFiles) {
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
// Start compacting files.
std::thread compaction_thread(
rocksdb::port::Thread compaction_thread(
[&] { EXPECT_OK(db->CompactFiles(CompactionOptions(), l0_files, 1)); });
// In the meantime flush another file.
@@ -253,6 +254,61 @@ TEST_F(CompactFilesTest, CapturingPendingFiles) {
delete db;
}
TEST_F(CompactFilesTest, CompactionFilterWithGetSv) {
class FilterWithGet : public CompactionFilter {
public:
virtual bool Filter(int level, const Slice& key, const Slice& value,
std::string* new_value,
bool* value_changed) const override {
if (db_ == nullptr) {
return true;
}
std::string res;
db_->Get(ReadOptions(), "", &res);
return true;
}
void SetDB(DB* db) {
db_ = db;
}
virtual const char* Name() const override { return "FilterWithGet"; }
private:
DB* db_;
};
std::shared_ptr<FilterWithGet> cf(new FilterWithGet());
Options options;
options.create_if_missing = true;
options.compaction_filter = cf.get();
DB* db = nullptr;
DestroyDB(db_name_, options);
Status s = DB::Open(options, db_name_, &db);
ASSERT_OK(s);
cf->SetDB(db);
// Write one L0 file
db->Put(WriteOptions(), "K1", "V1");
db->Flush(FlushOptions());
// Compact all L0 files using CompactFiles
rocksdb::ColumnFamilyMetaData meta;
db->GetColumnFamilyMetaData(&meta);
for (auto& file : meta.levels[0].files) {
std::string fname = file.db_path + "/" + file.name;
ASSERT_OK(
db->CompactFiles(rocksdb::CompactionOptions(), {fname}, 0));
}
delete db;
}
} // namespace rocksdb
int main(int argc, char** argv) {
+7
View File
@@ -76,6 +76,13 @@ class CompactedDBImpl : public DBImpl {
ColumnFamilyHandle* column_family) override {
return Status::NotSupported("Not supported in compacted db mode.");
}
using DB::IngestExternalFile;
virtual Status IngestExternalFile(
ColumnFamilyHandle* column_family,
const std::vector<std::string>& external_files,
const IngestExternalFileOptions& ingestion_options) override {
return Status::NotSupported("Not supported in compacted db mode.");
}
private:
friend class DB;
+3 -2
View File
@@ -8,6 +8,7 @@
#include <string>
#include <vector>
#include "port/port.h"
#include "util/testharness.h"
#include "util/testutil.h"
@@ -393,7 +394,7 @@ TEST_F(CompactionIteratorTest, ShuttingDownInFilter) {
compaction_proxy_->key_not_exists_beyond_output_level = true;
std::atomic<bool> seek_done{false};
std::thread compaction_thread([&] {
rocksdb::port::Thread compaction_thread([&] {
c_iter_->SeekToFirst();
EXPECT_FALSE(c_iter_->Valid());
EXPECT_TRUE(c_iter_->status().IsShutdownInProgress());
@@ -429,7 +430,7 @@ TEST_F(CompactionIteratorTest, ShuttingDownInMerge) {
compaction_proxy_->key_not_exists_beyond_output_level = true;
std::atomic<bool> seek_done{false};
std::thread compaction_thread([&] {
rocksdb::port::Thread compaction_thread([&] {
c_iter_->SeekToFirst();
ASSERT_FALSE(c_iter_->Valid());
ASSERT_TRUE(c_iter_->status().IsShutdownInProgress());
+5 -5
View File
@@ -45,7 +45,7 @@
#include "rocksdb/table.h"
#include "table/block.h"
#include "table/block_based_table_factory.h"
#include "table/merger.h"
#include "table/merging_iterator.h"
#include "table/table_builder.h"
#include "util/coding.h"
#include "util/file_reader_writer.h"
@@ -522,7 +522,7 @@ Status CompactionJob::Run() {
const uint64_t start_micros = env_->NowMicros();
// Launch a thread for each of subcompactions 1...num_threads-1
std::vector<std::thread> thread_pool;
std::vector<port::Thread> thread_pool;
thread_pool.reserve(num_threads - 1);
for (size_t i = 1; i < compact_->sub_compact_states.size(); i++) {
thread_pool.emplace_back(&CompactionJob::ProcessKeyValueCompaction, this,
@@ -771,9 +771,9 @@ void CompactionJob::ProcessKeyValueCompaction(SubcompactionState* sub_compact) {
key, sub_compact->current_output_file_size) &&
sub_compact->builder != nullptr) {
CompactionIterationStats range_del_out_stats;
status =
FinishCompactionOutputFile(input->status(), sub_compact,
range_del_agg.get(), &range_del_out_stats);
status = FinishCompactionOutputFile(input->status(), sub_compact,
range_del_agg.get(),
&range_del_out_stats, &key);
RecordDroppedKeys(range_del_out_stats,
&sub_compact->compaction_job_stats);
if (!status.ok()) {
+4 -1
View File
@@ -41,7 +41,10 @@ class CorruptionTest : public testing::Test {
DB* db_;
CorruptionTest() {
tiny_cache_ = NewLRUCache(100);
// If LRU cache shard bit is smaller than 2 (or -1 which will automatically
// set it to 0), test SequenceNumberRecovery will fail, likely because of a
// bug in recovery code. Keep it 4 for now to make the test passes.
tiny_cache_ = NewLRUCache(100, 4);
options_.wal_recovery_mode = WALRecoveryMode::kTolerateCorruptedTailRecords;
options_.env = &env_;
dbname_ = test::TmpDir() + "/corruption_test";
+3 -2
View File
@@ -9,6 +9,7 @@
#include "db/db_test_util.h"
#include "port/stack_trace.h"
#include "port/port.h"
#include "rocksdb/experimental.h"
#include "rocksdb/utilities/convenience.h"
#include "util/sync_point.h"
@@ -1101,7 +1102,7 @@ TEST_P(DBCompactionTestWithParam, ManualCompactionPartial) {
ASSERT_EQ(trivial_move, 6);
ASSERT_EQ(non_trivial_move, 0);
std::thread threads([&] {
rocksdb::port::Thread threads([&] {
compact_options.change_level = false;
compact_options.exclusive_manual_compaction = false;
std::string begin_string = Key(0);
@@ -1233,7 +1234,7 @@ TEST_F(DBCompactionTest, ManualPartialFill) {
ASSERT_EQ(trivial_move, 2);
ASSERT_EQ(non_trivial_move, 0);
std::thread threads([&] {
rocksdb::port::Thread threads([&] {
compact_options.change_level = false;
compact_options.exclusive_manual_compaction = false;
std::string begin_string = Key(0);
+3 -2
View File
@@ -13,6 +13,7 @@
#if !defined(ROCKSDB_LITE)
#include "db/db_test_util.h"
#include "port/port.h"
#include "port/stack_trace.h"
namespace rocksdb {
@@ -251,7 +252,7 @@ TEST_F(DBTestDynamicLevel, DynamicLevelMaxBytesBase2) {
});
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
std::thread thread([this] {
rocksdb::port::Thread thread([this] {
TEST_SYNC_POINT("DynamicLevelMaxBytesBase2:compact_range_start");
ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
TEST_SYNC_POINT("DynamicLevelMaxBytesBase2:compact_range_finish");
@@ -462,7 +463,7 @@ TEST_F(DBTestDynamicLevel, DISABLED_MigrateToDynamicLevelMaxBytesBase) {
compaction_finished = false;
// Issue manual compaction in one thread and still verify DB state
// in main thread.
std::thread t([&]() {
rocksdb::port::Thread t([&]() {
CompactRangeOptions compact_options;
compact_options.change_level = true;
compact_options.target_level = options.num_levels - 1;
+33
View File
@@ -9,6 +9,7 @@
#include "db/db_test_util.h"
#include "port/stack_trace.h"
#include "util/fault_injection_test_env.h"
#include "util/sync_point.h"
namespace rocksdb {
@@ -47,6 +48,38 @@ TEST_F(DBFlushTest, FlushWhileWritingManifest) {
#endif // ROCKSDB_LITE
}
TEST_F(DBFlushTest, SyncFail) {
std::unique_ptr<FaultInjectionTestEnv> fault_injection_env(
new FaultInjectionTestEnv(Env::Default()));
Options options;
options.disable_auto_compactions = true;
options.env = fault_injection_env.get();
SyncPoint::GetInstance()->LoadDependency(
{{"DBFlushTest::SyncFail:1", "DBImpl::SyncClosedLogs:Start"},
{"DBImpl::SyncClosedLogs:Failed", "DBFlushTest::SyncFail:2"}});
SyncPoint::GetInstance()->EnableProcessing();
Reopen(options);
Put("key", "value");
auto* cfd =
reinterpret_cast<ColumnFamilyHandleImpl*>(db_->DefaultColumnFamily())
->cfd();
int refs_before = cfd->current()->TEST_refs();
FlushOptions flush_options;
flush_options.wait = false;
ASSERT_OK(dbfull()->Flush(flush_options));
fault_injection_env->SetFilesystemActive(false);
TEST_SYNC_POINT("DBFlushTest::SyncFail:1");
TEST_SYNC_POINT("DBFlushTest::SyncFail:2");
fault_injection_env->SetFilesystemActive(true);
dbfull()->TEST_WaitForFlushMemTable();
ASSERT_EQ("", FilesPerLevel()); // flush failed.
// Flush job should release ref count to current version.
ASSERT_EQ(refs_before, cfd->current()->TEST_refs());
Destroy(options);
}
} // namespace rocksdb
int main(int argc, char** argv) {
+117 -64
View File
@@ -76,7 +76,7 @@
#include "rocksdb/write_buffer_manager.h"
#include "table/block.h"
#include "table/block_based_table_factory.h"
#include "table/merger.h"
#include "table/merging_iterator.h"
#include "table/table_builder.h"
#include "table/two_level_iterator.h"
#include "util/autovector.h"
@@ -268,6 +268,10 @@ static Status ValidateOptions(
"then direct I/O writes (use_direct_writes) must be disabled. ");
}
if (db_options.keep_log_file_num == 0) {
return Status::InvalidArgument("keep_log_file_num must be greater than 0");
}
return Status::OK();
}
@@ -342,6 +346,7 @@ DBImpl::DBImpl(const DBOptions& options, const std::string& dbname)
last_stats_dump_time_microsec_(0),
next_job_id_(1),
has_unpersisted_data_(false),
unable_to_flush_oldest_log_(false),
env_options_(BuildDBOptions(immutable_db_options_, mutable_db_options_)),
num_running_ingest_file_(0),
#ifndef ROCKSDB_LITE
@@ -663,6 +668,10 @@ void DBImpl::MaybeDumpStats() {
}
uint64_t DBImpl::FindMinPrepLogReferencedByMemTable() {
if (!allow_2pc()) {
return 0;
}
uint64_t min_log = 0;
// we must look through the memtables for two phase transactions
@@ -707,6 +716,11 @@ void DBImpl::MarkLogAsContainingPrepSection(uint64_t log) {
}
uint64_t DBImpl::FindMinLogContainingOutstandingPrep() {
if (!allow_2pc()) {
return 0;
}
std::lock_guard<std::mutex> lock(prep_heap_mutex_);
uint64_t min_log = 0;
@@ -1832,6 +1846,7 @@ Status DBImpl::WriteLevel0TableForRecovery(int job_id, ColumnFamilyData* cfd,
}
Status DBImpl::SyncClosedLogs(JobContext* job_context) {
TEST_SYNC_POINT("DBImpl::SyncClosedLogs:Start");
mutex_.AssertHeld();
autovector<log::Writer*, 1> logs_to_sync;
uint64_t current_log_number = logfile_number_;
@@ -1868,6 +1883,7 @@ Status DBImpl::SyncClosedLogs(JobContext* job_context) {
MarkLogsSynced(current_log_number - 1, true, s);
if (!s.ok()) {
bg_error_ = s;
TEST_SYNC_POINT("DBImpl::SyncClosedLogs:Failed");
return s;
}
}
@@ -1918,6 +1934,8 @@ Status DBImpl::FlushMemTableToOutputFile(
// is unlocked by the current thread.
if (s.ok()) {
s = flush_job.Run(&file_meta);
} else {
flush_job.Cancel();
}
if (s.ok()) {
@@ -2135,7 +2153,7 @@ Status DBImpl::CompactFiles(
immutable_db_options_.info_log.get());
// Perform CompactFiles
SuperVersion* sv = GetAndRefSuperVersion(cfd);
SuperVersion* sv = cfd->GetReferencedSuperVersion(&mutex_);
{
InstrumentedMutexLock l(&mutex_);
@@ -2147,7 +2165,12 @@ Status DBImpl::CompactFiles(
input_file_names, output_level,
output_path_id, &job_context, &log_buffer);
}
ReturnAndCleanupSuperVersion(cfd, sv);
if (sv->Unref()) {
mutex_.Lock();
sv->Cleanup();
mutex_.Unlock();
delete sv;
}
// Find and delete obsolete files
{
@@ -2505,7 +2528,7 @@ Status DBImpl::SetDBOptions(
mutable_db_options_ = new_options;
if (total_log_size_ > GetMaxTotalWalSize()) {
FlushColumnFamilies();
MaybeFlushColumnFamilies();
}
persist_options_status = PersistOptions();
@@ -2752,7 +2775,7 @@ void DBImpl::MarkLogsSynced(
++it;
}
}
assert(logs_.empty() || logs_[0].number > up_to ||
assert(!status.ok() || logs_.empty() || logs_[0].number > up_to ||
(logs_.size() == 1 && !logs_[0].getting_synced));
log_sync_cv_.SignalAll();
}
@@ -3977,15 +4000,32 @@ Status DBImpl::GetImpl(const ReadOptions& read_options,
auto cfh = reinterpret_cast<ColumnFamilyHandleImpl*>(column_family);
auto cfd = cfh->cfd();
// Acquire SuperVersion
SuperVersion* sv = GetAndRefSuperVersion(cfd);
TEST_SYNC_POINT("DBImpl::GetImpl:1");
TEST_SYNC_POINT("DBImpl::GetImpl:2");
SequenceNumber snapshot;
if (read_options.snapshot != nullptr) {
snapshot = reinterpret_cast<const SnapshotImpl*>(
read_options.snapshot)->number_;
} else {
// Since we get and reference the super version before getting
// the snapshot number, without a mutex protection, it is possible
// that a memtable switch happened in the middle and not all the
// data for this snapshot is available. But it will contain all
// the data available in the super version we have, which is also
// a valid snapshot to read from.
// We shouldn't get snapshot before finding and referencing the
// super versipon because a flush happening in between may compact
// away data for the snapshot, but the snapshot is earlier than the
// data overwriting it, so users may see wrong results.
snapshot = versions_->LastSequence();
}
// Acquire SuperVersion
SuperVersion* sv = GetAndRefSuperVersion(cfd);
TEST_SYNC_POINT("DBImpl::GetImpl:3");
TEST_SYNC_POINT("DBImpl::GetImpl:4");
// Prepare to store a list of merge operations if merge occurs.
MergeContext merge_context;
RangeDelAggregator range_del_agg(cfd->internal_comparator(), snapshot);
@@ -4698,9 +4738,8 @@ Status DBImpl::WriteImpl(const WriteOptions& write_options,
versions_->GetColumnFamilySet()->NumberOfColumnFamilies() == 1);
if (UNLIKELY(!single_column_family_mode_ &&
!alive_log_files_.begin()->getting_flushed &&
total_log_size_ > GetMaxTotalWalSize())) {
FlushColumnFamilies();
MaybeFlushColumnFamilies();
} else if (UNLIKELY(write_buffer_manager_->ShouldFlush())) {
// Before a new memtable is added in SwitchMemtable(),
// write_buffer_manager_->ShouldFlush() will keep returning true. If another
@@ -4785,6 +4824,7 @@ Status DBImpl::WriteImpl(const WriteOptions& write_options,
// and protects against concurrent loggers and concurrent writes
// into memtables
}
log::Writer* cur_log_writer = logs_.back().writer;
mutex_.Unlock();
@@ -4872,7 +4912,7 @@ Status DBImpl::WriteImpl(const WriteOptions& write_options,
WriteBatchInternal::SetSequence(merged_batch, current_sequence);
Slice log_entry = WriteBatchInternal::Contents(merged_batch);
status = logs_.back().writer->AddRecord(log_entry);
status = cur_log_writer->AddRecord(log_entry);
total_log_size_ += log_entry.size();
alive_log_files_.back().AddSize(log_entry.size());
log_empty_ = false;
@@ -5018,28 +5058,40 @@ Status DBImpl::WriteImpl(const WriteOptions& write_options,
return status;
}
void DBImpl::FlushColumnFamilies() {
void DBImpl::MaybeFlushColumnFamilies() {
mutex_.AssertHeld();
WriteContext context;
if (alive_log_files_.begin()->getting_flushed) {
return;
}
uint64_t flush_column_family_if_log_file = alive_log_files_.begin()->number;
alive_log_files_.begin()->getting_flushed = true;
auto oldest_alive_log = alive_log_files_.begin()->number;
auto oldest_log_with_uncommited_prep = FindMinLogContainingOutstandingPrep();
if (allow_2pc() &&
unable_to_flush_oldest_log_ &&
oldest_log_with_uncommited_prep > 0 &&
oldest_log_with_uncommited_prep <= oldest_alive_log) {
// we already attempted to flush all column families dependent on
// the oldest alive log but the log still contained uncommited transactions.
// the oldest alive log STILL contains uncommited transaction so there
// is still nothing that we can do.
return;
}
WriteContext context;
Log(InfoLogLevel::INFO_LEVEL, immutable_db_options_.info_log,
"Flushing all column families with data in WAL number %" PRIu64
". Total log size is %" PRIu64 " while max_total_wal_size is %" PRIu64,
flush_column_family_if_log_file, total_log_size_, GetMaxTotalWalSize());
oldest_alive_log, total_log_size_, GetMaxTotalWalSize());
// no need to refcount because drop is happening in write thread, so can't
// happen while we're in the write thread
for (auto cfd : *versions_->GetColumnFamilySet()) {
if (cfd->IsDropped()) {
continue;
}
if (cfd->GetLogNumber() <= flush_column_family_if_log_file) {
if (cfd->OldestLogToKeep() <= oldest_alive_log) {
auto status = SwitchMemtable(cfd, &context);
if (!status.ok()) {
break;
@@ -5049,6 +5101,26 @@ void DBImpl::FlushColumnFamilies() {
}
}
MaybeScheduleFlushOrCompaction();
// we only mark this log as getting flushed if we have successfully
// flushed all data in this log. If this log contains outstanding prepred
// transactions then we cannot flush this log until those transactions are commited.
unable_to_flush_oldest_log_ = false;
if (allow_2pc()) {
if (oldest_log_with_uncommited_prep == 0 ||
oldest_log_with_uncommited_prep > oldest_alive_log) {
// this log contains no outstanding prepared transactions
alive_log_files_.begin()->getting_flushed = true;
} else {
Log(InfoLogLevel::WARN_LEVEL, immutable_db_options_.info_log,
"Unable to release oldest log due to uncommited transaction");
unable_to_flush_oldest_log_ = true;
}
} else {
alive_log_files_.begin()->getting_flushed = true;
}
}
uint64_t DBImpl::GetMaxTotalWalSize() const {
@@ -5444,22 +5516,6 @@ SuperVersion* DBImpl::GetAndRefSuperVersion(uint32_t column_family_id) {
return GetAndRefSuperVersion(cfd);
}
// REQUIRED: mutex is NOT held
SuperVersion* DBImpl::GetAndRefSuperVersionUnlocked(uint32_t column_family_id) {
ColumnFamilyData* cfd;
{
InstrumentedMutexLock l(&mutex_);
auto column_family_set = versions_->GetColumnFamilySet();
cfd = column_family_set->GetColumnFamily(column_family_id);
}
if (!cfd) {
return nullptr;
}
return GetAndRefSuperVersion(cfd);
}
void DBImpl::ReturnAndCleanupSuperVersion(ColumnFamilyData* cfd,
SuperVersion* sv) {
bool unref_sv = !cfd->ReturnThreadLocalSuperVersion(sv);
@@ -5490,22 +5546,6 @@ void DBImpl::ReturnAndCleanupSuperVersion(uint32_t column_family_id,
ReturnAndCleanupSuperVersion(cfd, sv);
}
// REQUIRED: Mutex should NOT be held.
void DBImpl::ReturnAndCleanupSuperVersionUnlocked(uint32_t column_family_id,
SuperVersion* sv) {
ColumnFamilyData* cfd;
{
InstrumentedMutexLock l(&mutex_);
auto column_family_set = versions_->GetColumnFamilySet();
cfd = column_family_set->GetColumnFamily(column_family_id);
}
// If SuperVersion is held, and we successfully fetched a cfd using
// GetAndRefSuperVersion(), it must still exist.
assert(cfd != nullptr);
ReturnAndCleanupSuperVersion(cfd, sv);
}
// REQUIRED: this function should only be called on the write thread or if the
// mutex is held.
ColumnFamilyHandle* DBImpl::GetColumnFamilyHandle(uint32_t column_family_id) {
@@ -5518,23 +5558,33 @@ ColumnFamilyHandle* DBImpl::GetColumnFamilyHandle(uint32_t column_family_id) {
return cf_memtables->GetColumnFamilyHandle();
}
// REQUIRED: mutex is NOT held.
ColumnFamilyHandle* DBImpl::GetColumnFamilyHandleUnlocked(
uint32_t column_family_id) {
ColumnFamilyMemTables* cf_memtables = column_family_memtables_.get();
void DBImpl::GetApproximateMemTableStats(ColumnFamilyHandle* column_family,
const Range& range,
uint64_t* const count,
uint64_t* const size) {
ColumnFamilyHandleImpl* cfh =
reinterpret_cast<ColumnFamilyHandleImpl*>(column_family);
ColumnFamilyData* cfd = cfh->cfd();
SuperVersion* sv = GetAndRefSuperVersion(cfd);
InstrumentedMutexLock l(&mutex_);
// Convert user_key into a corresponding internal key.
InternalKey k1(range.start, kMaxSequenceNumber, kValueTypeForSeek);
InternalKey k2(range.limit, kMaxSequenceNumber, kValueTypeForSeek);
MemTable::MemTableStats memStats =
sv->mem->ApproximateStats(k1.Encode(), k2.Encode());
MemTable::MemTableStats immStats =
sv->imm->ApproximateStats(k1.Encode(), k2.Encode());
*count = memStats.count + immStats.count;
*size = memStats.size + immStats.size;
if (!cf_memtables->Seek(column_family_id)) {
return nullptr;
}
return cf_memtables->GetColumnFamilyHandle();
ReturnAndCleanupSuperVersion(cfd, sv);
}
void DBImpl::GetApproximateSizes(ColumnFamilyHandle* column_family,
const Range* range, int n, uint64_t* sizes,
bool include_memtable) {
uint8_t include_flags) {
assert(include_flags & DB::SizeApproximationFlags::INCLUDE_FILES ||
include_flags & DB::SizeApproximationFlags::INCLUDE_MEMTABLES);
Version* v;
auto cfh = reinterpret_cast<ColumnFamilyHandleImpl*>(column_family);
auto cfd = cfh->cfd();
@@ -5545,10 +5595,13 @@ void DBImpl::GetApproximateSizes(ColumnFamilyHandle* column_family,
// Convert user_key into a corresponding internal key.
InternalKey k1(range[i].start, kMaxSequenceNumber, kValueTypeForSeek);
InternalKey k2(range[i].limit, kMaxSequenceNumber, kValueTypeForSeek);
sizes[i] = versions_->ApproximateSize(v, k1.Encode(), k2.Encode());
if (include_memtable) {
sizes[i] += sv->mem->ApproximateSize(k1.Encode(), k2.Encode());
sizes[i] += sv->imm->ApproximateSize(k1.Encode(), k2.Encode());
sizes[i] = 0;
if (include_flags & DB::SizeApproximationFlags::INCLUDE_FILES) {
sizes[i] += versions_->ApproximateSize(v, k1.Encode(), k2.Encode());
}
if (include_flags & DB::SizeApproximationFlags::INCLUDE_MEMTABLES) {
sizes[i] += sv->mem->ApproximateStats(k1.Encode(), k2.Encode()).size;
sizes[i] += sv->imm->ApproximateStats(k1.Encode(), k2.Encode()).size;
}
}
+27 -12
View File
@@ -138,7 +138,13 @@ class DBImpl : public DB {
using DB::GetApproximateSizes;
virtual void GetApproximateSizes(ColumnFamilyHandle* column_family,
const Range* range, int n, uint64_t* sizes,
bool include_memtable = false) override;
uint8_t include_flags
= INCLUDE_FILES) override;
using DB::GetApproximateMemTableStats;
virtual void GetApproximateMemTableStats(ColumnFamilyHandle* column_family,
const Range& range,
uint64_t* const count,
uint64_t* const size) override;
using DB::CompactRange;
virtual Status CompactRange(const CompactRangeOptions& options,
ColumnFamilyHandle* column_family,
@@ -308,6 +314,16 @@ class DBImpl : public DB {
ColumnFamilyHandle* column_family = nullptr,
bool disallow_trivial_move = false);
void TEST_MaybeFlushColumnFamilies();
bool TEST_UnableToFlushOldestLog() {
return unable_to_flush_oldest_log_;
}
bool TEST_IsLogGettingFlushed() {
return alive_log_files_.begin()->getting_flushed;
}
// Force current memtable contents to be flushed.
Status TEST_FlushMemTable(bool wait = true,
ColumnFamilyHandle* cfh = nullptr);
@@ -420,9 +436,6 @@ class DBImpl : public DB {
// mutex is held.
SuperVersion* GetAndRefSuperVersion(uint32_t column_family_id);
// Same as above, should called without mutex held and not on write thread.
SuperVersion* GetAndRefSuperVersionUnlocked(uint32_t column_family_id);
// Un-reference the super version and return it to thread local cache if
// needed. If it is the last reference of the super version. Clean it up
// after un-referencing it.
@@ -433,18 +446,11 @@ class DBImpl : public DB {
// REQUIRED: this function should only be called on the write thread.
void ReturnAndCleanupSuperVersion(uint32_t colun_family_id, SuperVersion* sv);
// Same as above, should called without mutex held and not on write thread.
void ReturnAndCleanupSuperVersionUnlocked(uint32_t colun_family_id,
SuperVersion* sv);
// REQUIRED: this function should only be called on the write thread or if the
// mutex is held. Return value only valid until next call to this function or
// mutex is released.
ColumnFamilyHandle* GetColumnFamilyHandle(uint32_t column_family_id);
// Same as above, should called without mutex held and not on write thread.
ColumnFamilyHandle* GetColumnFamilyHandleUnlocked(uint32_t column_family_id);
// Returns the number of currently running flushes.
// REQUIREMENT: mutex_ must be held when calling this function.
int num_running_flushes() {
@@ -734,7 +740,7 @@ class DBImpl : public DB {
// REQUIRES: mutex locked
Status PersistOptions();
void FlushColumnFamilies();
void MaybeFlushColumnFamilies();
uint64_t GetMaxTotalWalSize() const;
@@ -994,6 +1000,15 @@ class DBImpl : public DB {
// Used when disableWAL is true.
bool has_unpersisted_data_;
// if an attempt was made to flush all column families that
// the oldest log depends on but uncommited data in the oldest
// log prevents the log from being released.
// We must attempt to free the dependent memtables again
// at a later time after the transaction in the oldest
// log is fully commited.
bool unable_to_flush_oldest_log_;
static const int KEEP_LOG_FILE_NUM = 1000;
// MSVC version 1800 still does not have constexpr for ::max()
static const uint64_t kNoTimeOut = port::kMaxUint64;
+5
View File
@@ -19,6 +19,11 @@ uint64_t DBImpl::TEST_GetLevel0TotalSize() {
return default_cf_handle_->cfd()->current()->storage_info()->NumLevelBytes(0);
}
void DBImpl::TEST_MaybeFlushColumnFamilies() {
InstrumentedMutexLock l(&mutex_);
MaybeFlushColumnFamilies();
}
int64_t DBImpl::TEST_MaxNextLevelOverlappingBytes(
ColumnFamilyHandle* column_family) {
ColumnFamilyData* cfd;
+8 -2
View File
@@ -79,7 +79,6 @@ class DBImplReadOnly : public DBImpl {
return Status::NotSupported("Not supported operation in read only mode.");
}
#ifndef ROCKSDB_LITE
virtual Status DisableFileDeletions() override {
return Status::NotSupported("Not supported operation in read only mode.");
}
@@ -92,7 +91,6 @@ class DBImplReadOnly : public DBImpl {
bool flush_memtable = true) override {
return Status::NotSupported("Not supported operation in read only mode.");
}
#endif // ROCKSDB_LITE
using DBImpl::Flush;
virtual Status Flush(const FlushOptions& options,
@@ -105,6 +103,14 @@ class DBImplReadOnly : public DBImpl {
return Status::NotSupported("Not supported operation in read only mode.");
}
using DB::IngestExternalFile;
virtual Status IngestExternalFile(
ColumnFamilyHandle* column_family,
const std::vector<std::string>& external_files,
const IngestExternalFileOptions& ingestion_options) override {
return Status::NotSupported("Not supported operation in read only mode.");
}
private:
friend class DB;
+6 -1
View File
@@ -341,6 +341,7 @@ void DBIter::Next() {
//
// NOTE: In between, saved_key_ can point to a user key that has
// a delete marker or a sequence number higher than sequence_
// saved_key_ MUST have a proper user_key before calling this function
//
// The prefix_check parameter controls whether we check the iterated
// keys against the prefix of the seeked key. Set to false when
@@ -946,7 +947,6 @@ void DBIter::Seek(const Slice& target) {
StopWatch sw(env_, statistics_, DB_SEEK);
ReleaseTempPinnedData();
saved_key_.Clear();
// now saved_key is used to store internal key.
saved_key_.SetInternalKey(target, sequence_);
{
@@ -961,6 +961,9 @@ void DBIter::Seek(const Slice& target) {
}
direction_ = kForward;
ClearSavedValue();
// convert the InternalKey to UserKey in saved_key_ before
// passed to FindNextUserEntry
saved_key_.Reserve(saved_key_.Size() - 8);
FindNextUserEntry(false /* not skipping */, prefix_same_as_start_);
if (!valid_) {
prefix_start_key_.clear();
@@ -1039,6 +1042,8 @@ void DBIter::SeekToFirst() {
RecordTick(statistics_, NUMBER_DB_SEEK);
if (iter_->Valid()) {
saved_key_.SetKey(ExtractUserKey(iter_->key()),
!iter_->IsKeyPinned() || !pin_thru_lifetime_ /* copy */);
FindNextUserEntry(false /* not skipping */, false /* no prefix check */);
if (statistics_ != nullptr) {
if (valid_) {
+61 -1
View File
@@ -16,7 +16,7 @@
#include "rocksdb/slice.h"
#include "rocksdb/statistics.h"
#include "table/iterator_wrapper.h"
#include "table/merger.h"
#include "table/merging_iterator.h"
#include "util/string_util.h"
#include "util/sync_point.h"
#include "util/testharness.h"
@@ -1897,6 +1897,66 @@ TEST_F(DBIteratorTest, DBIterator12) {
ASSERT_FALSE(db_iter->Valid());
}
TEST_F(DBIteratorTest, DBIterator13) {
Options options;
options.merge_operator = nullptr;
std::string key;
key.resize(9);
key.assign(9, static_cast<char>(0));
key[0] = 'b';
TestIterator* internal_iter = new TestIterator(BytewiseComparator());
internal_iter->AddPut(key, "0");
internal_iter->AddPut(key, "1");
internal_iter->AddPut(key, "2");
internal_iter->AddPut(key, "3");
internal_iter->AddPut(key, "4");
internal_iter->AddPut(key, "5");
internal_iter->AddPut(key, "6");
internal_iter->AddPut(key, "7");
internal_iter->AddPut(key, "8");
internal_iter->Finish();
std::unique_ptr<Iterator> db_iter(
NewDBIterator(env_, ImmutableCFOptions(options), BytewiseComparator(),
internal_iter, 2, 3, 0));
db_iter->Seek("b");
ASSERT_TRUE(db_iter->Valid());
ASSERT_EQ(db_iter->key().ToString(), key);
ASSERT_EQ(db_iter->value().ToString(), "2");
}
TEST_F(DBIteratorTest, DBIterator14) {
Options options;
options.merge_operator = nullptr;
std::string key("b");
TestIterator* internal_iter = new TestIterator(BytewiseComparator());
internal_iter->AddPut("b", "0");
internal_iter->AddPut("b", "1");
internal_iter->AddPut("b", "2");
internal_iter->AddPut("b", "3");
internal_iter->AddPut("a", "4");
internal_iter->AddPut("a", "5");
internal_iter->AddPut("a", "6");
internal_iter->AddPut("c", "7");
internal_iter->AddPut("c", "8");
internal_iter->AddPut("c", "9");
internal_iter->Finish();
std::unique_ptr<Iterator> db_iter(
NewDBIterator(env_, ImmutableCFOptions(options), BytewiseComparator(),
internal_iter, 4, 1, 0));
db_iter->Seek("b");
ASSERT_TRUE(db_iter->Valid());
ASSERT_EQ(db_iter->key().ToString(), "b");
ASSERT_EQ(db_iter->value().ToString(), "3");
db_iter->SeekToFirst();
ASSERT_EQ(db_iter->key().ToString(), "a");
ASSERT_EQ(db_iter->value().ToString(), "4");
}
class DBIterWithMergeIterTest : public testing::Test {
public:
DBIterWithMergeIterTest()
+1 -1
View File
@@ -1644,7 +1644,7 @@ TEST_F(DBIteratorTest, IteratorWithLocalStatistics) {
std::atomic<uint64_t> total_prev_found(0);
std::atomic<uint64_t> total_bytes(0);
std::vector<std::thread> threads;
std::vector<port::Thread> threads;
std::function<void()> reader_func_next = [&]() {
Iterator* iter = db_->NewIterator(ReadOptions());
+207 -1
View File
@@ -112,6 +112,81 @@ TEST_F(DBRangeDelTest, CompactionOutputFilesExactlyFilled) {
db_->ReleaseSnapshot(snapshot);
}
TEST_F(DBRangeDelTest, MaxCompactionBytesCutsOutputFiles) {
// Ensures range deletion spanning multiple compaction output files that are
// cut by max_compaction_bytes will have non-overlapping key-ranges.
// https://github.com/facebook/rocksdb/issues/1778
const int kNumFiles = 2, kNumPerFile = 1 << 8, kBytesPerVal = 1 << 12;
Options opts = CurrentOptions();
opts.comparator = test::Uint64Comparator();
opts.disable_auto_compactions = true;
opts.level0_file_num_compaction_trigger = kNumFiles;
opts.max_compaction_bytes = kNumPerFile * kBytesPerVal;
opts.memtable_factory.reset(new SpecialSkipListFactory(kNumPerFile));
// Want max_compaction_bytes to trigger the end of compaction output file, not
// target_file_size_base, so make the latter much bigger
opts.target_file_size_base = 100 * opts.max_compaction_bytes;
Reopen(opts);
// snapshot protects range tombstone from dropping due to becoming obsolete.
const Snapshot* snapshot = db_->GetSnapshot();
// It spans the whole key-range, thus will be included in all output files
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
GetNumericStr(0),
GetNumericStr(kNumFiles * kNumPerFile - 1)));
Random rnd(301);
for (int i = 0; i < kNumFiles; ++i) {
std::vector<std::string> values;
// Write 1MB (256 values, each 4K)
for (int j = 0; j < kNumPerFile; j++) {
values.push_back(RandomString(&rnd, kBytesPerVal));
ASSERT_OK(Put(GetNumericStr(kNumPerFile * i + j), values[j]));
}
// extra entry to trigger SpecialSkipListFactory's flush
ASSERT_OK(Put(GetNumericStr(kNumPerFile), ""));
dbfull()->TEST_WaitForFlushMemTable();
ASSERT_EQ(i + 1, NumTableFilesAtLevel(0));
}
dbfull()->TEST_CompactRange(0, nullptr, nullptr, nullptr,
true /* disallow_trivial_move */);
ASSERT_EQ(0, NumTableFilesAtLevel(0));
ASSERT_GE(NumTableFilesAtLevel(1), 2);
std::vector<std::vector<FileMetaData>> files;
dbfull()->TEST_GetFilesMetaData(db_->DefaultColumnFamily(), &files);
for (size_t i = 0; i < files[1].size() - 1; ++i) {
ASSERT_TRUE(InternalKeyComparator(opts.comparator)
.Compare(files[1][i].largest, files[1][i + 1].smallest) <
0);
}
db_->ReleaseSnapshot(snapshot);
}
TEST_F(DBRangeDelTest, SentinelsOmittedFromOutputFile) {
// Regression test for bug where sentinel range deletions (i.e., ones with
// sequence number of zero) were included in output files.
// snapshot protects range tombstone from dropping due to becoming obsolete.
const Snapshot* snapshot = db_->GetSnapshot();
// gaps between ranges creates sentinels in our internal representation
std::vector<std::pair<std::string, std::string>> range_dels = {{"a", "b"}, {"c", "d"}, {"e", "f"}};
for (const auto& range_del : range_dels) {
ASSERT_OK(db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
range_del.first, range_del.second));
}
ASSERT_OK(db_->Flush(FlushOptions()));
ASSERT_EQ(1, NumTableFilesAtLevel(0));
std::vector<std::vector<FileMetaData>> files;
dbfull()->TEST_GetFilesMetaData(db_->DefaultColumnFamily(), &files);
ASSERT_GT(files[0][0].smallest_seqno, 0);
db_->ReleaseSnapshot(snapshot);
}
TEST_F(DBRangeDelTest, FlushRangeDelsSameStartKey) {
db_->Put(WriteOptions(), "b1", "val");
ASSERT_OK(
@@ -428,7 +503,80 @@ TEST_F(DBRangeDelTest, ObsoleteTombstoneCleanup) {
db_->ReleaseSnapshot(snapshot);
}
#endif // ROCKSDB_LITE
TEST_F(DBRangeDelTest, TableEvictedDuringScan) {
// The RangeDelAggregator holds pointers into range deletion blocks created by
// table readers. This test ensures the aggregator can still access those
// blocks even if it outlives the table readers that created them.
//
// DBIter always keeps readers open for L0 files. So, in order to test
// aggregator outliving reader, we need to have deletions in L1 files, which
// are opened/closed on-demand during the scan. This is accomplished by
// setting kNumRanges > level0_stop_writes_trigger, which prevents deletions
// from all lingering in L0 (there is at most one range deletion per L0 file).
//
// The first L1 file will contain a range deletion since its begin key is 0.
// SeekToFirst() references that table's reader and adds its range tombstone
// to the aggregator. Upon advancing beyond that table's key-range via Next(),
// the table reader will be unreferenced by the iterator. Since we manually
// call Evict() on all readers before the full scan, this unreference causes
// the reader's refcount to drop to zero and thus be destroyed.
//
// When it is destroyed, we do not remove its range deletions from the
// aggregator. So, subsequent calls to Next() must be able to use these
// deletions to decide whether a key is covered. This will work as long as
// the aggregator properly references the range deletion block.
const int kNum = 25, kRangeBegin = 0, kRangeEnd = 7, kNumRanges = 5;
Options opts = CurrentOptions();
opts.comparator = test::Uint64Comparator();
opts.level0_file_num_compaction_trigger = 4;
opts.level0_stop_writes_trigger = 4;
opts.memtable_factory.reset(new SpecialSkipListFactory(1));
opts.num_levels = 2;
BlockBasedTableOptions bbto;
bbto.cache_index_and_filter_blocks = true;
bbto.block_cache = NewLRUCache(8 << 20);
opts.table_factory.reset(NewBlockBasedTableFactory(bbto));
Reopen(opts);
// Hold a snapshot so range deletions can't become obsolete during compaction
// to bottommost level (i.e., L1).
const Snapshot* snapshot = db_->GetSnapshot();
for (int i = 0; i < kNum; ++i) {
db_->Put(WriteOptions(), GetNumericStr(i), "val");
if (i > 0) {
dbfull()->TEST_WaitForFlushMemTable();
}
if (i >= kNum / 2 && i < kNum / 2 + kNumRanges) {
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(),
GetNumericStr(kRangeBegin), GetNumericStr(kRangeEnd));
}
}
// Must be > 1 so the first L1 file can be closed before scan finishes
dbfull()->TEST_WaitForCompact();
ASSERT_GT(NumTableFilesAtLevel(1), 1);
std::vector<uint64_t> file_numbers = ListTableFiles(env_, dbname_);
ReadOptions read_opts;
auto* iter = db_->NewIterator(read_opts);
int expected = kRangeEnd;
iter->SeekToFirst();
for (auto file_number : file_numbers) {
// This puts table caches in the state of being externally referenced only
// so they are destroyed immediately upon iterator unreferencing.
TableCache::Evict(dbfull()->TEST_table_cache(), file_number);
}
for (; iter->Valid(); iter->Next()) {
ASSERT_EQ(GetNumericStr(expected), iter->key());
++expected;
// Keep clearing block cache's LRU so range deletion block can be freed as
// soon as its refcount drops to zero.
bbto.block_cache->EraseUnRefEntries();
}
ASSERT_EQ(kNum, expected);
delete iter;
db_->ReleaseSnapshot(snapshot);
}
TEST_F(DBRangeDelTest, GetCoveredKeyFromMutableMemtable) {
db_->Put(WriteOptions(), "key", "val");
@@ -475,6 +623,36 @@ TEST_F(DBRangeDelTest, GetCoveredKeyFromSst) {
db_->ReleaseSnapshot(snapshot);
}
TEST_F(DBRangeDelTest, GetCoveredMergeOperandFromMemtable) {
const int kNumMergeOps = 10;
Options opts = CurrentOptions();
opts.merge_operator = MergeOperators::CreateUInt64AddOperator();
Reopen(opts);
for (int i = 0; i < kNumMergeOps; ++i) {
std::string val;
PutFixed64(&val, i);
db_->Merge(WriteOptions(), "key", val);
if (i == kNumMergeOps / 2) {
// deletes [0, 5]
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "key",
"key_");
}
}
ReadOptions read_opts;
std::string expected, actual;
ASSERT_OK(db_->Get(read_opts, "key", &actual));
PutFixed64(&expected, 30); // 6+7+8+9
ASSERT_EQ(expected, actual);
expected.clear();
read_opts.ignore_range_deletions = true;
ASSERT_OK(db_->Get(read_opts, "key", &actual));
PutFixed64(&expected, 45); // 0+1+2+...+9
ASSERT_EQ(expected, actual);
}
TEST_F(DBRangeDelTest, GetIgnoresRangeDeletions) {
Options opts = CurrentOptions();
opts.max_write_buffer_number = 4;
@@ -603,6 +781,34 @@ TEST_F(DBRangeDelTest, IteratorIgnoresRangeDeletions) {
db_->ReleaseSnapshot(snapshot);
}
TEST_F(DBRangeDelTest, TailingIteratorRangeTombstoneUnsupported) {
db_->Put(WriteOptions(), "key", "val");
// snapshot prevents key from being deleted during flush
const Snapshot* snapshot = db_->GetSnapshot();
ASSERT_OK(
db_->DeleteRange(WriteOptions(), db_->DefaultColumnFamily(), "a", "z"));
// iterations check unsupported in memtable, l0, and then l1
for (int i = 0; i < 3; ++i) {
ReadOptions read_opts;
read_opts.tailing = true;
auto* iter = db_->NewIterator(read_opts);
if (i == 2) {
// For L1+, iterators over files are created on-demand, so need seek
iter->SeekToFirst();
}
ASSERT_TRUE(iter->status().IsNotSupported());
delete iter;
if (i == 0) {
ASSERT_OK(db_->Flush(FlushOptions()));
} else if (i == 1) {
MoveFilesToLevel(1);
}
}
db_->ReleaseSnapshot(snapshot);
}
#endif // ROCKSDB_LITE
} // namespace rocksdb
int main(int argc, char** argv) {
+1 -1
View File
@@ -613,7 +613,7 @@ TEST_F(DBSSTTest, OpenDBWithInfiniteMaxOpenFiles) {
}
Close();
// Reopening the DB will load all exisitng files
// Reopening the DB will load all existing files
Reopen(options);
ASSERT_EQ("12,0,12", FilesPerLevel(0));
std::vector<std::vector<FileMetaData>> files;
+82 -17
View File
@@ -31,6 +31,7 @@
#include "db/version_set.h"
#include "db/write_batch_internal.h"
#include "memtable/hash_linklist_rep.h"
#include "port/port.h"
#include "port/stack_trace.h"
#include "rocksdb/cache.h"
#include "rocksdb/compaction_filter.h"
@@ -998,7 +999,7 @@ TEST_F(DBTest, FlushSchedule) {
options.max_write_buffer_number = 2;
options.write_buffer_size = 120 * 1024;
CreateAndReopenWithCF({"pikachu"}, options);
std::vector<std::thread> threads;
std::vector<port::Thread> threads;
std::atomic<int> thread_num(0);
// each column family will have 5 thread, each thread generating 2 memtables.
@@ -1407,17 +1408,19 @@ TEST_F(DBTest, ApproximateSizesMemTable) {
std::string start = Key(50);
std::string end = Key(60);
Range r(start, end);
db_->GetApproximateSizes(&r, 1, &size, true);
uint8_t include_both = DB::SizeApproximationFlags::INCLUDE_FILES |
DB::SizeApproximationFlags::INCLUDE_MEMTABLES;
db_->GetApproximateSizes(&r, 1, &size, include_both);
ASSERT_GT(size, 6000);
ASSERT_LT(size, 204800);
// Zero if not including mem table
db_->GetApproximateSizes(&r, 1, &size, false);
db_->GetApproximateSizes(&r, 1, &size);
ASSERT_EQ(size, 0);
start = Key(500);
end = Key(600);
r = Range(start, end);
db_->GetApproximateSizes(&r, 1, &size, true);
db_->GetApproximateSizes(&r, 1, &size, include_both);
ASSERT_EQ(size, 0);
for (int i = 0; i < N; i++) {
@@ -1427,13 +1430,13 @@ TEST_F(DBTest, ApproximateSizesMemTable) {
start = Key(500);
end = Key(600);
r = Range(start, end);
db_->GetApproximateSizes(&r, 1, &size, true);
db_->GetApproximateSizes(&r, 1, &size, include_both);
ASSERT_EQ(size, 0);
start = Key(100);
end = Key(1020);
r = Range(start, end);
db_->GetApproximateSizes(&r, 1, &size, true);
db_->GetApproximateSizes(&r, 1, &size, include_both);
ASSERT_GT(size, 6000);
options.max_write_buffer_number = 8;
@@ -1456,28 +1459,28 @@ TEST_F(DBTest, ApproximateSizesMemTable) {
start = Key(100);
end = Key(300);
r = Range(start, end);
db_->GetApproximateSizes(&r, 1, &size, true);
db_->GetApproximateSizes(&r, 1, &size, include_both);
ASSERT_EQ(size, 0);
start = Key(1050);
end = Key(1080);
r = Range(start, end);
db_->GetApproximateSizes(&r, 1, &size, true);
db_->GetApproximateSizes(&r, 1, &size, include_both);
ASSERT_GT(size, 6000);
start = Key(2100);
end = Key(2300);
r = Range(start, end);
db_->GetApproximateSizes(&r, 1, &size, true);
db_->GetApproximateSizes(&r, 1, &size, include_both);
ASSERT_EQ(size, 0);
start = Key(1050);
end = Key(1080);
r = Range(start, end);
uint64_t size_with_mt, size_without_mt;
db_->GetApproximateSizes(&r, 1, &size_with_mt, true);
db_->GetApproximateSizes(&r, 1, &size_with_mt, include_both);
ASSERT_GT(size_with_mt, 6000);
db_->GetApproximateSizes(&r, 1, &size_without_mt, false);
db_->GetApproximateSizes(&r, 1, &size_without_mt);
ASSERT_EQ(size_without_mt, 0);
Flush();
@@ -1489,12 +1492,65 @@ TEST_F(DBTest, ApproximateSizesMemTable) {
start = Key(1050);
end = Key(1080);
r = Range(start, end);
db_->GetApproximateSizes(&r, 1, &size_with_mt, true);
db_->GetApproximateSizes(&r, 1, &size_without_mt, false);
db_->GetApproximateSizes(&r, 1, &size_with_mt, include_both);
db_->GetApproximateSizes(&r, 1, &size_without_mt);
ASSERT_GT(size_with_mt, size_without_mt);
ASSERT_GT(size_without_mt, 6000);
}
TEST_F(DBTest, GetApproximateMemTableStats) {
Options options = CurrentOptions();
options.write_buffer_size = 100000000;
options.compression = kNoCompression;
options.create_if_missing = true;
DestroyAndReopen(options);
const int N = 128;
Random rnd(301);
for (int i = 0; i < N; i++) {
ASSERT_OK(Put(Key(i), RandomString(&rnd, 1024)));
}
uint64_t count;
uint64_t size;
std::string start = Key(50);
std::string end = Key(60);
Range r(start, end);
db_->GetApproximateMemTableStats(r, &count, &size);
ASSERT_GT(count, 0);
ASSERT_LE(count, N);
ASSERT_GT(size, 6000);
ASSERT_LT(size, 204800);
start = Key(500);
end = Key(600);
r = Range(start, end);
db_->GetApproximateMemTableStats(r, &count, &size);
ASSERT_EQ(count, 0);
ASSERT_EQ(size, 0);
Flush();
start = Key(50);
end = Key(60);
r = Range(start, end);
db_->GetApproximateMemTableStats(r, &count, &size);
ASSERT_EQ(count, 0);
ASSERT_EQ(size, 0);
for (int i = 0; i < N; i++) {
ASSERT_OK(Put(Key(1000 + i), RandomString(&rnd, 1024)));
}
start = Key(100);
end = Key(1020);
r = Range(start, end);
db_->GetApproximateMemTableStats(r, &count, &size);
ASSERT_GT(count, 20);
ASSERT_GT(size, 6000);
}
TEST_F(DBTest, ApproximateSizes) {
do {
Options options = CurrentOptions();
@@ -2813,11 +2869,20 @@ class ModelDB : public DB {
using DB::GetApproximateSizes;
virtual void GetApproximateSizes(ColumnFamilyHandle* column_family,
const Range* range, int n, uint64_t* sizes,
bool include_memtable) override {
uint8_t include_flags
= INCLUDE_FILES) override {
for (int i = 0; i < n; i++) {
sizes[i] = 0;
}
}
using DB::GetApproximateMemTableStats;
virtual void GetApproximateMemTableStats(ColumnFamilyHandle* column_family,
const Range& range,
uint64_t* const count,
uint64_t* const size) override {
*count = 0;
*size = 0;
}
using DB::CompactRange;
virtual Status CompactRange(const CompactRangeOptions& options,
ColumnFamilyHandle* column_family,
@@ -3492,7 +3557,7 @@ TEST_F(DBTest, SanitizeNumThreads) {
}
TEST_F(DBTest, WriteSingleThreadEntry) {
std::vector<std::thread> threads;
std::vector<port::Thread> threads;
dbfull()->TEST_LockMutex();
auto w = dbfull()->TEST_BeginWrite();
threads.emplace_back([&] { Put("a", "b"); });
@@ -5370,7 +5435,7 @@ TEST_F(DBTest, FlushesInParallelWithCompactRange) {
}
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
std::vector<std::thread> threads;
std::vector<port::Thread> threads;
threads.emplace_back([&]() { Compact("a", "z"); });
TEST_SYNC_POINT("DBTest::FlushesInParallelWithCompactRange:1");
@@ -5776,7 +5841,7 @@ TEST_F(DBTest, PauseBackgroundWorkTest) {
options.write_buffer_size = 100000; // Small write buffer
Reopen(options);
std::vector<std::thread> threads;
std::vector<port::Thread> threads;
std::atomic<bool> done(false);
db_->PauseBackgroundWork();
threads.emplace_back([&]() {
+86 -6
View File
@@ -11,6 +11,7 @@
#include <functional>
#include "db/db_test_util.h"
#include "port/port.h"
#include "port/stack_trace.h"
#include "rocksdb/persistent_cache.h"
#include "rocksdb/wal_filter.h"
@@ -1616,8 +1617,8 @@ TEST_F(DBTest2, SyncPointMarker) {
CountSyncPoint();
};
auto thread1 = std::thread(func1);
auto thread2 = std::thread(func2);
auto thread1 = port::Thread(func1);
auto thread2 = port::Thread(func2);
thread1.join();
thread2.join();
@@ -1906,8 +1907,8 @@ TEST_P(MergeOperatorPinningTest, TailingIterator) {
delete iter;
};
std::thread writer_thread(writer_func);
std::thread reader_thread(reader_func);
rocksdb::port::Thread writer_thread(writer_func);
rocksdb::port::Thread reader_thread(reader_func);
writer_thread.join();
reader_thread.join();
@@ -2178,7 +2179,7 @@ TEST_F(DBTest2, ManualCompactionOverlapManualCompaction) {
cro.exclusive_manual_compaction = false;
ASSERT_OK(db_->CompactRange(cro, &k1s, &k2s));
};
std::thread bg_thread;
rocksdb::port::Thread bg_thread;
// While the compaction is running, we will create 2 new files that
// can fit in L1, these 2 files will be moved to L1 and overlap with
@@ -2199,7 +2200,7 @@ TEST_F(DBTest2, ManualCompactionOverlapManualCompaction) {
ASSERT_OK(Flush());
// Start a non-exclusive manual compaction in a bg thread
bg_thread = std::thread(bg_manual_compact);
bg_thread = port::Thread(bg_manual_compact);
// This manual compaction conflict with the other manual compaction
// so it should wait until the first compaction finish
env_->SleepForMicroseconds(1000000);
@@ -2216,8 +2217,87 @@ TEST_F(DBTest2, ManualCompactionOverlapManualCompaction) {
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
}
TEST_F(DBTest2, OptimizeForPointLookup) {
Options options = CurrentOptions();
Close();
options.OptimizeForPointLookup(2);
ASSERT_OK(DB::Open(options, dbname_, &db_));
ASSERT_OK(Put("foo", "v1"));
ASSERT_EQ("v1", Get("foo"));
Flush();
ASSERT_EQ("v1", Get("foo"));
}
#endif // ROCKSDB_LITE
TEST_F(DBTest2, GetRaceFlush1) {
ASSERT_OK(Put("foo", "v1"));
rocksdb::SyncPoint::GetInstance()->LoadDependency(
{{"DBImpl::GetImpl:1", "DBTest2::GetRaceFlush:1"},
{"DBTest2::GetRaceFlush:2", "DBImpl::GetImpl:2"}});
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
rocksdb::port::Thread t1([&] {
TEST_SYNC_POINT("DBTest2::GetRaceFlush:1");
ASSERT_OK(Put("foo", "v2"));
Flush();
TEST_SYNC_POINT("DBTest2::GetRaceFlush:2");
});
// Get() is issued after the first Put(), so it should see either
// "v1" or "v2".
ASSERT_NE("NOT_FOUND", Get("foo"));
t1.join();
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
}
TEST_F(DBTest2, GetRaceFlush2) {
ASSERT_OK(Put("foo", "v1"));
rocksdb::SyncPoint::GetInstance()->LoadDependency(
{{"DBImpl::GetImpl:3", "DBTest2::GetRaceFlush:1"},
{"DBTest2::GetRaceFlush:2", "DBImpl::GetImpl:4"}});
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
port::Thread t1([&] {
TEST_SYNC_POINT("DBTest2::GetRaceFlush:1");
ASSERT_OK(Put("foo", "v2"));
Flush();
TEST_SYNC_POINT("DBTest2::GetRaceFlush:2");
});
// Get() is issued after the first Put(), so it should see either
// "v1" or "v2".
ASSERT_NE("NOT_FOUND", Get("foo"));
t1.join();
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
}
TEST_F(DBTest2, DirectIO) {
if (!IsDirectIOSupported()) {
return;
}
Options options = CurrentOptions();
options.use_direct_reads = options.use_direct_writes = true;
options.allow_mmap_reads = options.allow_mmap_writes = false;
DestroyAndReopen(options);
ASSERT_OK(Put(Key(0), "a"));
ASSERT_OK(Put(Key(5), "a"));
ASSERT_OK(Flush());
ASSERT_OK(Put(Key(10), "a"));
ASSERT_OK(Put(Key(15), "a"));
ASSERT_OK(Flush());
ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
Reopen(options);
}
} // namespace rocksdb
int main(int argc, char** argv) {
+11 -1
View File
@@ -72,7 +72,12 @@ DBTestBase::~DBTestBase() {
options.db_paths.emplace_back(dbname_ + "_2", 0);
options.db_paths.emplace_back(dbname_ + "_3", 0);
options.db_paths.emplace_back(dbname_ + "_4", 0);
EXPECT_OK(DestroyDB(dbname_, options));
if (getenv("KEEP_DB")) {
printf("DB is still at %s\n", dbname_.c_str());
} else {
EXPECT_OK(DestroyDB(dbname_, options));
}
delete env_;
}
@@ -348,6 +353,11 @@ Options DBTestBase::CurrentOptions(
options.prefix_extractor.reset(NewNoopTransform());
break;
}
case kBlockBasedTableWithPartitionedIndex: {
table_options.index_type = BlockBasedTableOptions::kTwoLevelIndexSearch;
options.prefix_extractor.reset(NewNoopTransform());
break;
}
case kBlockBasedTableWithIndexRestartInterval: {
table_options.index_block_restart_interval = 8;
break;
+26 -1
View File
@@ -231,6 +231,20 @@ class SpecialEnv : public EnvWrapper {
return base_->Append(data);
}
}
Status PositionedAppend(const Slice& data, uint64_t offset) override {
if (env_->table_write_callback_) {
(*env_->table_write_callback_)();
}
if (env_->drop_writes_.load(std::memory_order_acquire)) {
// Drop writes on the floor
return Status::OK();
} else if (env_->no_space_.load(std::memory_order_acquire)) {
return Status::NoSpace("No space left on device");
} else {
env_->bytes_written_ += data.size();
return base_->PositionedAppend(data, offset);
}
}
Status Truncate(uint64_t size) override { return base_->Truncate(size); }
Status Close() override {
// SyncPoint is not supported in Released Windows Mode.
@@ -257,6 +271,9 @@ class SpecialEnv : public EnvWrapper {
Env::IOPriority GetIOPriority() override {
return base_->GetIOPriority();
}
bool use_direct_io() const override {
return base_->use_direct_io();
}
};
class ManifestFile : public WritableFile {
public:
@@ -358,7 +375,14 @@ class SpecialEnv : public EnvWrapper {
return Status::IOError("simulated write error");
}
Status s = target()->NewWritableFile(f, r, soptions);
EnvOptions optimized = soptions;
if (strstr(f.c_str(), "MANIFEST") != nullptr ||
strstr(f.c_str(), "log") != nullptr) {
optimized.use_mmap_writes = false;
optimized.use_direct_writes = false;
}
Status s = target()->NewWritableFile(f, r, optimized);
if (s.ok()) {
if (strstr(f.c_str(), ".sst") != nullptr) {
r->reset(new SSTableFile(this, std::move(*r)));
@@ -594,6 +618,7 @@ class DBTestBase : public testing::Test {
kLevelSubcompactions = 31,
kUniversalSubcompactions = 32,
kBlockBasedTableWithIndexRestartInterval = 33,
kBlockBasedTableWithPartitionedIndex = 34,
};
int option_config_;
+3 -2
View File
@@ -8,6 +8,7 @@
// found in the LICENSE file. See the AUTHORS file for names of contributors.
#include "db/db_test_util.h"
#include "port/port.h"
#include "port/stack_trace.h"
#include "util/fault_injection_test_env.h"
#include "util/options_helper.h"
@@ -86,7 +87,7 @@ TEST_F(DBWALTest, SyncWALNotBlockWrite) {
});
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
std::thread thread([&]() { ASSERT_OK(db_->SyncWAL()); });
rocksdb::port::Thread thread([&]() { ASSERT_OK(db_->SyncWAL()); });
TEST_SYNC_POINT("DBWALTest::SyncWALNotBlockWrite:1");
ASSERT_OK(Put("foo2", "bar2"));
@@ -118,7 +119,7 @@ TEST_F(DBWALTest, SyncWALNotWaitWrite) {
});
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
std::thread thread([&]() { ASSERT_OK(Put("foo2", "bar2")); });
rocksdb::port::Thread thread([&]() { ASSERT_OK(Put("foo2", "bar2")); });
TEST_SYNC_POINT("DBWALTest::SyncWALNotWaitWrite:1");
ASSERT_OK(db_->SyncWAL());
TEST_SYNC_POINT("DBWALTest::SyncWALNotWaitWrite:2");
+10 -2
View File
@@ -13,7 +13,7 @@
#include <vector>
#include "db/version_edit.h"
#include "table/merger.h"
#include "table/merging_iterator.h"
#include "table/scoped_arena_iterator.h"
#include "table/sst_file_writer_collectors.h"
#include "table/table_builder.h"
@@ -306,8 +306,16 @@ Status ExternalSstFileIngestionJob::GetIngestedFileInfo(
if (file_to_ingest->global_seqno_offset == 0) {
return Status::Corruption("Was not able to find file global seqno field");
}
} else if (file_to_ingest->version == 1) {
// SST file V1 should not have global seqno field
assert(seqno_iter == uprops.end());
if (ingestion_options_.allow_blocking_flush ||
ingestion_options_.allow_global_seqno) {
return Status::InvalidArgument(
"External SST file V1 does not support global seqno");
}
} else {
return Status::InvalidArgument("external file version is not supported");
return Status::InvalidArgument("External file version is not supported");
}
// Get number of entries in table
file_to_ingest->num_entries = props->num_entries;
+11 -11
View File
@@ -258,11 +258,11 @@ TEST_F(ExternalSSTFileTest, Basic) {
ASSERT_EQ(Get(Key(k)), Key(k) + "_val");
}
// This file has overlapping values with the exisitng data
// This file has overlapping values with the existing data
s = DeprecatedAddFile({file3});
ASSERT_FALSE(s.ok()) << s.ToString();
// This file has overlapping values with the exisitng data
// This file has overlapping values with the existing data
s = DeprecatedAddFile({file4});
ASSERT_FALSE(s.ok()) << s.ToString();
@@ -510,7 +510,7 @@ TEST_F(ExternalSSTFileTest, AddList) {
ASSERT_EQ(user_props["xyz_Count"], "100");
}
// This file list has overlapping values with the exisitng data
// This file list has overlapping values with the existing data
s = DeprecatedAddFile(file_list3);
ASSERT_FALSE(s.ok()) << s.ToString();
@@ -705,7 +705,7 @@ TEST_F(ExternalSSTFileTest, NoCopy) {
ASSERT_TRUE(s.ok()) << s.ToString();
ASSERT_OK(env_->FileExists(file2));
// This file have overlapping values with the exisitng data
// This file have overlapping values with the existing data
s = DeprecatedAddFile({file2}, true /* move file */);
ASSERT_FALSE(s.ok()) << s.ToString();
ASSERT_OK(env_->FileExists(file3));
@@ -821,7 +821,7 @@ TEST_F(ExternalSSTFileTest, MultiThreaded) {
ASSERT_TRUE(s.ok()) << s.ToString();
};
// Write num_files files in parallel
std::vector<std::thread> sst_writer_threads;
std::vector<port::Thread> sst_writer_threads;
for (int i = 0; i < num_files; ++i) {
sst_writer_threads.emplace_back(write_file_func);
}
@@ -864,7 +864,7 @@ TEST_F(ExternalSSTFileTest, MultiThreaded) {
};
// Bulk load num_files files in parallel
std::vector<std::thread> add_file_threads;
std::vector<port::Thread> add_file_threads;
DestroyAndReopen(options);
for (int i = 0; i < num_files; ++i) {
add_file_threads.emplace_back(load_file_func);
@@ -1108,13 +1108,13 @@ TEST_F(ExternalSSTFileTest, PickedLevelBug) {
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
// While writing the MANIFEST start a thread that will ask for compaction
std::thread bg_compact([&]() {
rocksdb::port::Thread bg_compact([&]() {
ASSERT_OK(db_->CompactRange(CompactRangeOptions(), nullptr, nullptr));
});
TEST_SYNC_POINT("ExternalSSTFileTest::PickedLevelBug:2");
// Start a thread that will ingest a new file
std::thread bg_addfile([&]() {
rocksdb::port::Thread bg_addfile([&]() {
file_keys = {1, 2, 3};
ASSERT_OK(GenerateAndAddExternalFile(options, file_keys, 1));
});
@@ -1169,7 +1169,7 @@ TEST_F(ExternalSSTFileTest, CompactDuringAddFileRandom) {
ASSERT_OK(GenerateAndAddExternalFile(options, file_keys, range_id));
};
std::vector<std::thread> threads;
std::vector<port::Thread> threads;
while (range_id < 5000) {
int range_start = range_id * 10;
int range_end = range_start + 10;
@@ -1728,7 +1728,7 @@ TEST_F(ExternalSSTFileTest, CompactionDeadlock) {
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
// Start ingesting and extrnal file in the background
std::thread bg_ingest_file([&]() {
rocksdb::port::Thread bg_ingest_file([&]() {
running_threads += 1;
ASSERT_OK(GenerateAndAddExternalFile(options, {5, 6}));
running_threads -= 1;
@@ -1748,7 +1748,7 @@ TEST_F(ExternalSSTFileTest, CompactionDeadlock) {
// This thread will try to insert into the memtable but since we have 4 L0
// files this thread will be blocked and hold the writer thread
std::thread bg_block_put([&]() {
rocksdb::port::Thread bg_block_put([&]() {
running_threads += 1;
ASSERT_OK(Put(Key(10), "memtable"));
running_threads -= 1;
+7 -1
View File
@@ -38,7 +38,7 @@
#include "rocksdb/table.h"
#include "table/block.h"
#include "table/block_based_table_factory.h"
#include "table/merger.h"
#include "table/merging_iterator.h"
#include "table/table_builder.h"
#include "table/two_level_iterator.h"
#include "util/coding.h"
@@ -230,6 +230,12 @@ Status FlushJob::Run(FileMetaData* file_meta) {
return s;
}
void FlushJob::Cancel() {
db_mutex_->AssertHeld();
assert(base_ != nullptr);
base_->Unref();
}
Status FlushJob::WriteLevel0Table() {
AutoThreadOperationStageUpdater stage_updater(
ThreadStatus::STAGE_FLUSH_WRITE_L0);
+3 -1
View File
@@ -67,9 +67,11 @@ class FlushJob {
~FlushJob();
// Require db_mutex held
// Require db_mutex held.
// Once PickMemTable() is called, either Run() or Cancel() has to be call.
void PickMemTable();
Status Run(FileMetaData* file_meta = nullptr);
void Cancel();
TableProperties GetTableProperties() const { return table_properties_; }
private:
+40 -5
View File
@@ -18,7 +18,7 @@
#include "rocksdb/env.h"
#include "rocksdb/slice.h"
#include "rocksdb/slice_transform.h"
#include "table/merger.h"
#include "table/merging_iterator.h"
#include "util/string_util.h"
#include "util/sync_point.h"
@@ -69,12 +69,18 @@ class LevelIterator : public InternalIterator {
delete file_iter_;
}
RangeDelAggregator range_del_agg(
cfd_->internal_comparator(), {} /* snapshots */);
file_iter_ = cfd_->table_cache()->NewIterator(
read_options_, *(cfd_->soptions()), cfd_->internal_comparator(),
files_[file_index_]->fd, nullptr /* range_del_agg */,
files_[file_index_]->fd, read_options_.ignore_range_deletions ? nullptr : &range_del_agg,
nullptr /* table_reader_ptr */, nullptr, false);
file_iter_->SetPinnedItersMgr(pinned_iters_mgr_);
if (!range_del_agg.IsEmpty()) {
status_ = Status::NotSupported(
"Range tombstones unsupported with ForwardIterator");
valid_ = false;
}
}
void SeekToLast() override {
status_ = Status::NotSupported("LevelIterator::SeekToLast()");
@@ -558,8 +564,17 @@ void ForwardIterator::RebuildIterators(bool refresh_sv) {
// New
sv_ = cfd_->GetReferencedSuperVersion(&(db_->mutex_));
}
RangeDelAggregator range_del_agg(
InternalKeyComparator(cfd_->internal_comparator()), {} /* snapshots */);
mutable_iter_ = sv_->mem->NewIterator(read_options_, &arena_);
sv_->imm->AddIterators(read_options_, &imm_iters_, &arena_);
if (!read_options_.ignore_range_deletions) {
std::unique_ptr<InternalIterator> range_del_iter(
sv_->mem->NewRangeTombstoneIterator(read_options_));
range_del_agg.AddTombstones(std::move(range_del_iter));
sv_->imm->AddRangeTombstoneIterators(read_options_, &arena_,
&range_del_agg);
}
has_iter_trimmed_for_upper_bound_ = false;
const auto* vstorage = sv_->current->storage_info();
@@ -575,13 +590,18 @@ void ForwardIterator::RebuildIterators(bool refresh_sv) {
}
l0_iters_.push_back(cfd_->table_cache()->NewIterator(
read_options_, *cfd_->soptions(), cfd_->internal_comparator(), l0->fd,
nullptr /* range_del_agg */));
read_options_.ignore_range_deletions ? nullptr : &range_del_agg));
}
BuildLevelIterators(vstorage);
current_ = nullptr;
is_prev_set_ = false;
UpdateChildrenPinnedItersMgr();
if (!range_del_agg.IsEmpty()) {
status_ = Status::NotSupported(
"Range tombstones unsupported with ForwardIterator");
valid_ = false;
}
}
void ForwardIterator::RenewIterators() {
@@ -599,6 +619,15 @@ void ForwardIterator::RenewIterators() {
mutable_iter_ = svnew->mem->NewIterator(read_options_, &arena_);
svnew->imm->AddIterators(read_options_, &imm_iters_, &arena_);
RangeDelAggregator range_del_agg(
InternalKeyComparator(cfd_->internal_comparator()), {} /* snapshots */);
if (!read_options_.ignore_range_deletions) {
std::unique_ptr<InternalIterator> range_del_iter(
svnew->mem->NewRangeTombstoneIterator(read_options_));
range_del_agg.AddTombstones(std::move(range_del_iter));
sv_->imm->AddRangeTombstoneIterators(read_options_, &arena_,
&range_del_agg);
}
const auto* vstorage = sv_->current->storage_info();
const auto& l0_files = vstorage->LevelFiles(0);
@@ -630,7 +659,8 @@ void ForwardIterator::RenewIterators() {
}
l0_iters_new.push_back(cfd_->table_cache()->NewIterator(
read_options_, *cfd_->soptions(), cfd_->internal_comparator(),
l0_files_new[inew]->fd, nullptr /* range_del_agg */));
l0_files_new[inew]->fd,
read_options_.ignore_range_deletions ? nullptr : &range_del_agg));
}
for (auto* f : l0_iters_) {
@@ -650,6 +680,11 @@ void ForwardIterator::RenewIterators() {
sv_ = svnew;
UpdateChildrenPinnedItersMgr();
if (!range_del_agg.IsEmpty()) {
status_ = Status::NotSupported(
"Range tombstones unsupported with ForwardIterator");
valid_ = false;
}
}
void ForwardIterator::BuildLevelIterators(const VersionStorageInfo* vstorage) {
+6 -5
View File
@@ -34,6 +34,7 @@ int main() { return 0; }
#include "rocksdb/db.h"
#include "rocksdb/status.h"
#include "rocksdb/table.h"
#include "port/port.h"
#include "util/testharness.h"
const int MAX_SHARDS = 100000;
@@ -94,7 +95,7 @@ struct Reader {
explicit Reader(std::vector<ShardState>* shard_states, rocksdb::DB* db)
: shard_states_(shard_states), db_(db) {
sem_init(&sem_, 0, 0);
thread_ = std::thread(&Reader::run, this);
thread_ = port::Thread(&Reader::run, this);
}
void run() {
@@ -193,7 +194,7 @@ struct Reader {
char pad1[128] __attribute__((__unused__));
std::vector<ShardState>* shard_states_;
rocksdb::DB* db_;
std::thread thread_;
rocksdb::port::Thread thread_;
sem_t sem_;
std::mutex queue_mutex_;
std::bitset<MAX_SHARDS + 1> shards_pending_set_;
@@ -206,7 +207,7 @@ struct Writer {
explicit Writer(std::vector<ShardState>* shard_states, rocksdb::DB* db)
: shard_states_(shard_states), db_(db) {}
void start() { thread_ = std::thread(&Writer::run, this); }
void start() { thread_ = port::Thread(&Writer::run, this); }
void run() {
std::queue<std::chrono::steady_clock::time_point> workq;
@@ -263,7 +264,7 @@ struct Writer {
char pad1[128] __attribute__((__unused__));
std::vector<ShardState>* shard_states_;
rocksdb::DB* db_;
std::thread thread_;
rocksdb::port::Thread thread_;
char pad2[128] __attribute__((__unused__));
};
@@ -313,7 +314,7 @@ struct StatsThread {
rocksdb::DB* db_;
std::mutex cvm_;
std::condition_variable cv_;
std::thread thread_;
rocksdb::port::Thread thread_;
std::atomic<bool> done_{false};
};
+3 -4
View File
@@ -865,7 +865,7 @@ void InternalStats::DumpCFMapStats(std::map<std::string, double>* cf_stats) {
}
}
int InternalStats::DumpCFMapStats(
void InternalStats::DumpCFMapStats(
std::map<int, std::map<LevelStatType, double>>* levels_stats,
CompactionStats* compaction_stats_sum) {
const VersionStorageInfo* vstorage = cfd_->current()->storage_info();
@@ -925,7 +925,6 @@ int InternalStats::DumpCFMapStats(
PrepareLevelStats(&sum_stats, total_files, total_files_being_compacted,
total_file_size, 0, w_amp, *compaction_stats_sum);
(*levels_stats)[-1] = sum_stats; // -1 is for the Sum level
return num_levels_to_check;
}
void InternalStats::DumpCFStats(std::string* value) {
@@ -937,8 +936,8 @@ void InternalStats::DumpCFStats(std::string* value) {
// Print stats for each level
std::map<int, std::map<LevelStatType, double>> levels_stats;
CompactionStats compaction_stats_sum(0);
int levels = DumpCFMapStats(&levels_stats, &compaction_stats_sum);
for (int l = 0; l < levels; ++l) {
DumpCFMapStats(&levels_stats, &compaction_stats_sum);
for (int l = 0; l < number_levels_; ++l) {
if (levels_stats.find(l) != levels_stats.end()) {
PrintLevelStats(buf, sizeof(buf), "L" + ToString(l), levels_stats[l]);
value->append(buf);
+1 -1
View File
@@ -273,7 +273,7 @@ class InternalStats {
private:
void DumpDBStats(std::string* value);
void DumpCFMapStats(std::map<std::string, double>* cf_stats);
int DumpCFMapStats(
void DumpCFMapStats(
std::map<int, std::map<LevelStatType, double>>* level_stats,
CompactionStats* compaction_stats_sum);
void DumpCFStats(std::string* value);
+1 -1
View File
@@ -19,7 +19,7 @@
#include "rocksdb/env.h"
#include "rocksdb/slice.h"
#include "rocksdb/slice_transform.h"
#include "table/merger.h"
#include "table/merging_iterator.h"
#include "util/xfunc.h"
namespace rocksdb {
+7 -7
View File
@@ -26,7 +26,7 @@
#include "rocksdb/write_buffer_manager.h"
#include "table/internal_iterator.h"
#include "table/iterator_wrapper.h"
#include "table/merger.h"
#include "table/merging_iterator.h"
#include "util/arena.h"
#include "util/autovector.h"
#include "util/coding.h"
@@ -390,16 +390,16 @@ port::RWMutex* MemTable::GetLock(const Slice& key) {
return &locks_[hash(key) % locks_.size()];
}
uint64_t MemTable::ApproximateSize(const Slice& start_ikey,
const Slice& end_ikey) {
MemTable::MemTableStats MemTable::ApproximateStats(const Slice& start_ikey,
const Slice& end_ikey) {
uint64_t entry_count = table_->ApproximateNumEntries(start_ikey, end_ikey);
entry_count += range_del_table_->ApproximateNumEntries(start_ikey, end_ikey);
if (entry_count == 0) {
return 0;
return {0, 0};
}
uint64_t n = num_entries_.load(std::memory_order_relaxed);
if (n == 0) {
return 0;
return {0, 0};
}
if (entry_count > n) {
// (range_del_)table_->ApproximateNumEntries() is just an estimate so it can
@@ -408,7 +408,7 @@ uint64_t MemTable::ApproximateSize(const Slice& start_ikey,
entry_count = n;
}
uint64_t data_size = data_size_.load(std::memory_order_relaxed);
return entry_count * (data_size / n);
return {entry_count * (data_size / n), entry_count};
}
void MemTable::Add(SequenceNumber s, ValueType type,
@@ -560,7 +560,7 @@ static bool SaveValue(void* arg, const char* entry) {
ValueType type;
UnPackSequenceAndType(tag, &s->seq, &type);
if ((type == kTypeValue || type == kTypeDeletion) &&
if ((type == kTypeValue || type == kTypeMerge) &&
range_del_agg->ShouldDelete(Slice(key_ptr, key_length))) {
type = kTypeRangeDeletion;
}
+7 -1
View File
@@ -326,7 +326,13 @@ class MemTable {
return table_->IsSnapshotSupported() && !moptions_.inplace_update_support;
}
uint64_t ApproximateSize(const Slice& start_ikey, const Slice& end_ikey);
struct MemTableStats {
uint64_t size;
uint64_t count;
};
MemTableStats ApproximateStats(const Slice& start_ikey,
const Slice& end_ikey);
// Get the lock associated for the key
port::RWMutex* GetLock(const Slice& key);
+8 -6
View File
@@ -16,7 +16,7 @@
#include "rocksdb/db.h"
#include "rocksdb/env.h"
#include "rocksdb/iterator.h"
#include "table/merger.h"
#include "table/merging_iterator.h"
#include "util/coding.h"
#include "util/log_buffer.h"
#include "util/sync_point.h"
@@ -190,13 +190,15 @@ uint64_t MemTableListVersion::GetTotalNumEntries() const {
return total_num;
}
uint64_t MemTableListVersion::ApproximateSize(const Slice& start_ikey,
const Slice& end_ikey) {
uint64_t total_size = 0;
MemTable::MemTableStats MemTableListVersion::ApproximateStats(
const Slice& start_ikey, const Slice& end_ikey) {
MemTable::MemTableStats total_stats = {0, 0};
for (auto& m : memlist_) {
total_size += m->ApproximateSize(start_ikey, end_ikey);
auto mStats = m->ApproximateStats(start_ikey, end_ikey);
total_stats.size += mStats.size;
total_stats.count += mStats.count;
}
return total_size;
return total_stats;
}
uint64_t MemTableListVersion::GetTotalNumDeletes() const {
+4 -1
View File
@@ -95,7 +95,8 @@ class MemTableListVersion {
uint64_t GetTotalNumDeletes() const;
uint64_t ApproximateSize(const Slice& start_ikey, const Slice& end_ikey);
MemTable::MemTableStats ApproximateStats(const Slice& start_ikey,
const Slice& end_ikey);
// Returns the value of MemTable::GetEarliestSequenceNumber() on the most
// recent MemTable in this list or kMaxSequenceNumber if the list is empty.
@@ -221,6 +222,8 @@ class MemTableList {
// PickMemtablesToFlush() is called.
void FlushRequested() { flush_requested_ = true; }
bool HasFlushRequested() { return flush_requested_; }
// Copying allowed
// MemTableList(const MemTableList&);
// void operator=(const MemTableList&);
+6 -6
View File
@@ -426,7 +426,7 @@ class Benchmark {
virtual ~Benchmark() {}
virtual void Run() {
std::cout << "Number of threads: " << num_threads_ << std::endl;
std::vector<std::thread> threads;
std::vector<port::Thread> threads;
uint64_t bytes_written = 0;
uint64_t bytes_read = 0;
uint64_t read_hits = 0;
@@ -457,7 +457,7 @@ class Benchmark {
}
}
virtual void RunThreads(std::vector<std::thread>* threads,
virtual void RunThreads(std::vector<port::Thread>* threads,
uint64_t* bytes_written, uint64_t* bytes_read,
bool write, uint64_t* read_hits) = 0;
@@ -478,7 +478,7 @@ class FillBenchmark : public Benchmark {
num_write_ops_per_thread_ = FLAGS_num_operations;
}
void RunThreads(std::vector<std::thread>* threads, uint64_t* bytes_written,
void RunThreads(std::vector<port::Thread>* threads, uint64_t* bytes_written,
uint64_t* bytes_read, bool write,
uint64_t* read_hits) override {
FillBenchmarkThread(table_, key_gen_, bytes_written, bytes_read, sequence_,
@@ -494,7 +494,7 @@ class ReadBenchmark : public Benchmark {
num_read_ops_per_thread_ = FLAGS_num_operations / FLAGS_num_threads;
}
void RunThreads(std::vector<std::thread>* threads, uint64_t* bytes_written,
void RunThreads(std::vector<port::Thread>* threads, uint64_t* bytes_written,
uint64_t* bytes_read, bool write,
uint64_t* read_hits) override {
for (int i = 0; i < FLAGS_num_threads; ++i) {
@@ -518,7 +518,7 @@ class SeqReadBenchmark : public Benchmark {
num_read_ops_per_thread_ = FLAGS_num_scans;
}
void RunThreads(std::vector<std::thread>* threads, uint64_t* bytes_written,
void RunThreads(std::vector<port::Thread>* threads, uint64_t* bytes_written,
uint64_t* bytes_read, bool write,
uint64_t* read_hits) override {
for (int i = 0; i < FLAGS_num_threads; ++i) {
@@ -545,7 +545,7 @@ class ReadWriteBenchmark : public Benchmark {
num_write_ops_per_thread_ = FLAGS_num_operations;
}
void RunThreads(std::vector<std::thread>* threads, uint64_t* bytes_written,
void RunThreads(std::vector<port::Thread>* threads, uint64_t* bytes_written,
uint64_t* bytes_read, bool write,
uint64_t* read_hits) override {
std::atomic_int threads_done;
+2 -1
View File
@@ -12,6 +12,7 @@
#include "rocksdb/memtablerep.h"
#include "rocksdb/perf_context.h"
#include "rocksdb/slice_transform.h"
#include "port/port.h"
#include "util/histogram.h"
#include "util/instrumented_mutex.h"
#include "util/stop_watch.h"
@@ -561,7 +562,7 @@ TEST_F(PerfContextTest, DBMutexLockCounter) {
for (int c = 0; c < 2; ++c) {
InstrumentedMutex mutex(nullptr, Env::Default(), stats_code[c]);
mutex.Lock();
std::thread child_thread([&] {
rocksdb::port::Thread child_thread([&] {
SetPerfLevel(perf_level);
perf_context.Reset();
ASSERT_EQ(perf_context.db_mutex_lock_nanos, 0);
+4 -3
View File
@@ -420,9 +420,10 @@ void RangeDelAggregator::AddToBuilder(
RangeTombstone tombstone;
if (collapse_deletions_) {
auto next_tombstone_map_iter = std::next(tombstone_map_iter);
if (next_tombstone_map_iter == stripe_map_iter->second.raw_map.end()) {
// it's the sentinel tombstone
break;
if (next_tombstone_map_iter == stripe_map_iter->second.raw_map.end() ||
tombstone_map_iter->second.seq_ == 0) {
// it's a sentinel tombstone
continue;
}
tombstone.start_key_ = tombstone_map_iter->first;
tombstone.end_key_ = next_tombstone_map_iter->first;
+2 -1
View File
@@ -28,6 +28,7 @@
#include "db/internal_stats.h"
#include "db/table_cache.h"
#include "db/version_set.h"
#include "port/port.h"
#include "table/table_reader.h"
namespace rocksdb {
@@ -359,7 +360,7 @@ class VersionBuilder::Rep {
if (max_threads <= 1) {
load_handlers_func();
} else {
std::vector<std::thread> threads;
std::vector<port::Thread> threads;
for (int i = 0; i < max_threads; i++) {
threads.emplace_back(load_handlers_func);
}
+1 -1
View File
@@ -40,7 +40,7 @@
#include "table/format.h"
#include "table/get_context.h"
#include "table/internal_iterator.h"
#include "table/merger.h"
#include "table/merging_iterator.h"
#include "table/meta_blocks.h"
#include "table/plain_table_factory.h"
#include "table/table_reader.h"
+2
View File
@@ -520,6 +520,8 @@ class Version {
return next_;
}
int TEST_refs() const { return refs_; }
VersionStorageInfo* storage_info() { return &storage_info_; }
VersionSet* version_set() { return vset_; }
+2 -1
View File
@@ -14,6 +14,7 @@
#include "db/write_callback.h"
#include "rocksdb/db.h"
#include "rocksdb/write_batch.h"
#include "port/port.h"
#include "util/logging.h"
#include "util/sync_point.h"
#include "util/testharness.h"
@@ -241,7 +242,7 @@ TEST_F(WriteCallbackTest, WriteWithCallbackTest) {
rocksdb::SyncPoint::GetInstance()->EnableProcessing();
// do all the writes
std::vector<std::thread> threads;
std::vector<port::Thread> threads;
for (uint32_t i = 0; i < write_group.size(); i++) {
threads.emplace_back(write_with_callback_func);
}
+1 -1
View File
@@ -317,7 +317,7 @@ void WriteThread::LaunchParallelFollowers(ParallelGroup* pg,
while (w != pg->last_writer) {
// Writers that won't write don't get sequence allotment
if (!w->CallbackFailed()) {
if (!w->CallbackFailed() && w->ShouldWriteToMemtable()) {
sequence += WriteBatchInternal::Count(w->batch);
}
w = w->link_newer;
@@ -0,0 +1,15 @@
---
title: RocksDB 5.1.2 Released!
layout: post
author: maysamyabandeh
category: blog
---
### Public API Change
* Support dynamically change `delete_obsolete_files_period_micros` option via SetDBOptions().
* Added EventListener::OnExternalFileIngested which will be called when IngestExternalFile() add a file successfully.
* BackupEngine::Open and BackupEngineReadOnly::Open now always return error statuses matching those of the backup Env.
### Bug Fixes
* Fix the bug that if 2PC is enabled, checkpoints may loss some recent transactions.
* When file copying is needed when creating checkpoints or bulk loading files, fsync the file after the file copying.
+16
View File
@@ -289,6 +289,10 @@ extern ROCKSDB_LIBRARY_API void rocksdb_release_snapshot(
Else returns a pointer to a malloc()-ed null-terminated value. */
extern ROCKSDB_LIBRARY_API char* rocksdb_property_value(rocksdb_t* db,
const char* propname);
/* returns 0 on success, -1 otherwise */
int rocksdb_property_int(
rocksdb_t* db,
const char* propname, uint64_t *out_val);
extern ROCKSDB_LIBRARY_API char* rocksdb_property_value_cf(
rocksdb_t* db, rocksdb_column_family_handle_t* column_family,
@@ -448,6 +452,10 @@ extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_iterate(
void (*deleted)(void*, const char* k, size_t klen));
extern ROCKSDB_LIBRARY_API const char* rocksdb_writebatch_data(
rocksdb_writebatch_t*, size_t* size);
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_set_save_point(
rocksdb_writebatch_t*);
extern ROCKSDB_LIBRARY_API void rocksdb_writebatch_rollback_to_save_point(
rocksdb_writebatch_t*, char** errptr);
/* Block based table options */
@@ -521,6 +529,8 @@ extern ROCKSDB_LIBRARY_API void rocksdb_options_set_cuckoo_table_factory(
rocksdb_options_t* opt, rocksdb_cuckoo_table_options_t* table_options);
/* Options */
extern ROCKSDB_LIBRARY_API void rocksdb_set_options(
rocksdb_t* db, int count, const char* const keys[], const char* const values[], char** errptr);
extern ROCKSDB_LIBRARY_API rocksdb_options_t* rocksdb_options_create();
extern ROCKSDB_LIBRARY_API void rocksdb_options_destroy(rocksdb_options_t*);
@@ -630,6 +640,10 @@ extern ROCKSDB_LIBRARY_API void rocksdb_options_set_soft_rate_limit(
rocksdb_options_t*, double);
extern ROCKSDB_LIBRARY_API void rocksdb_options_set_hard_rate_limit(
rocksdb_options_t*, double);
extern ROCKSDB_LIBRARY_API void rocksdb_options_set_soft_pending_compaction_bytes_limit(
rocksdb_options_t* opt, size_t v);
extern ROCKSDB_LIBRARY_API void rocksdb_options_set_hard_pending_compaction_bytes_limit(
rocksdb_options_t* opt, size_t v);
extern ROCKSDB_LIBRARY_API void
rocksdb_options_set_rate_limit_delay_max_milliseconds(rocksdb_options_t*,
unsigned int);
@@ -695,6 +709,8 @@ extern ROCKSDB_LIBRARY_API void rocksdb_options_set_disable_data_sync(
rocksdb_options_t*, int);
extern ROCKSDB_LIBRARY_API void rocksdb_options_set_disable_auto_compactions(
rocksdb_options_t*, int);
extern ROCKSDB_LIBRARY_API void rocksdb_options_set_optimize_filters_for_hits(
rocksdb_options_t*, int);
extern ROCKSDB_LIBRARY_API void
rocksdb_options_set_delete_obsolete_files_period_micros(rocksdb_options_t*,
uint64_t);
+4 -2
View File
@@ -39,8 +39,10 @@ class Cache;
// is set, insert to the cache will fail when cache is full. User can also
// set percentage of the cache reserves for high priority entries via
// high_pri_pool_pct.
// num_shard_bits = -1 means it is automatically determined: every shard
// will be at least 512KB and number of shard bits will not exceed 6.
extern std::shared_ptr<Cache> NewLRUCache(size_t capacity,
int num_shard_bits = 6,
int num_shard_bits = -1,
bool strict_capacity_limit = false,
double high_pri_pool_ratio = 0.0);
@@ -50,7 +52,7 @@ extern std::shared_ptr<Cache> NewLRUCache(size_t capacity,
//
// Return nullptr if it is not supported.
extern std::shared_ptr<Cache> NewClockCache(size_t capacity,
int num_shard_bits = 6,
int num_shard_bits = -1,
bool strict_capacity_limit = false);
class Cache {
+51 -7
View File
@@ -464,7 +464,7 @@ class DB {
static const std::string kNumDeletesImmMemTables;
// "rocksdb.estimate-num-keys" - returns estimated number of total keys in
// the active and unflushed immutable memtables.
// the active and unflushed immutable memtables and storage.
static const std::string kEstimateNumKeys;
// "rocksdb.estimate-table-readers-mem" - returns estimated memory used for
@@ -586,6 +586,14 @@ class DB {
virtual bool GetAggregatedIntProperty(const Slice& property,
uint64_t* value) = 0;
// Flags for DB::GetSizeApproximation that specify whether memtable
// stats should be included, or file stats approximation or both
enum SizeApproximationFlags : uint8_t {
NONE = 0,
INCLUDE_MEMTABLES = 1,
INCLUDE_FILES = 1 << 1
};
// For each i in [0,n-1], store in "sizes[i]", the approximate
// file system space used by keys in "[range[i].start .. range[i].limit)".
//
@@ -593,16 +601,52 @@ class DB {
// if the user data compresses by a factor of ten, the returned
// sizes will be one-tenth the size of the corresponding user data size.
//
// If include_memtable is set to true, then the result will also
// include those recently written data in the mem-tables if
// the mem-table type supports it.
// If include_flags defines whether the returned size should include
// the recently written data in the mem-tables (if
// the mem-table type supports it), data serialized to disk, or both.
// include_flags should be of type DB::SizeApproximationFlags
virtual void GetApproximateSizes(ColumnFamilyHandle* column_family,
const Range* range, int n, uint64_t* sizes,
bool include_memtable = false) = 0;
uint8_t include_flags
= INCLUDE_FILES) = 0;
virtual void GetApproximateSizes(const Range* range, int n, uint64_t* sizes,
bool include_memtable = false) {
uint8_t include_flags
= INCLUDE_FILES) {
GetApproximateSizes(DefaultColumnFamily(), range, n, sizes,
include_memtable);
include_flags);
}
// The method is similar to GetApproximateSizes, except it
// returns approximate number of records in memtables.
virtual void GetApproximateMemTableStats(ColumnFamilyHandle* column_family,
const Range& range,
uint64_t* const count,
uint64_t* const size) = 0;
virtual void GetApproximateMemTableStats(const Range& range,
uint64_t* const count,
uint64_t* const size) {
GetApproximateMemTableStats(DefaultColumnFamily(), range, count, size);
}
// Deprecated versions of GetApproximateSizes
ROCKSDB_DEPRECATED_FUNC virtual void GetApproximateSizes(
const Range* range, int n, uint64_t* sizes,
bool include_memtable) {
uint8_t include_flags = SizeApproximationFlags::INCLUDE_FILES;
if (include_memtable) {
include_flags |= SizeApproximationFlags::INCLUDE_MEMTABLES;
}
GetApproximateSizes(DefaultColumnFamily(), range, n, sizes, include_flags);
}
ROCKSDB_DEPRECATED_FUNC virtual void GetApproximateSizes(
ColumnFamilyHandle* column_family,
const Range* range, int n, uint64_t* sizes,
bool include_memtable) {
uint8_t include_flags = SizeApproximationFlags::INCLUDE_FILES;
if (include_memtable) {
include_flags |= SizeApproximationFlags::INCLUDE_MEMTABLES;
}
GetApproximateSizes(column_family, range, n, sizes, include_flags);
}
// Compact the underlying storage for the key range [*begin,*end].
+126 -115
View File
@@ -17,7 +17,10 @@
#include <limits>
#include <unordered_map>
#include "rocksdb/comparator.h"
#include "rocksdb/env.h"
#include "rocksdb/listener.h"
#include "rocksdb/memtablerep.h"
#include "rocksdb/universal_compaction.h"
#include "rocksdb/version.h"
#include "rocksdb/write_buffer_manager.h"
@@ -230,7 +233,7 @@ struct ColumnFamilyOptions {
// REQUIRES: The client must ensure that the comparator supplied
// here has the same name and orders keys *exactly* the same as the
// comparator provided to previous open calls on the same DB.
const Comparator* comparator;
const Comparator* comparator = BytewiseComparator();
// REQUIRES: The client must provide a merge operator if Merge operation
// needs to be accessed. Calling Merge on a DB without a merge operator
@@ -242,7 +245,7 @@ struct ColumnFamilyOptions {
// for the first time. It's necessary to specify a merge operator when
// openning the DB in this case.
// Default: nullptr
std::shared_ptr<MergeOperator> merge_operator;
std::shared_ptr<MergeOperator> merge_operator = nullptr;
// A single CompactionFilter instance to call into during compaction.
// Allows an application to modify/delete a key-value during background
@@ -259,7 +262,7 @@ struct ColumnFamilyOptions {
// thread-safe.
//
// Default: nullptr
const CompactionFilter* compaction_filter;
const CompactionFilter* compaction_filter = nullptr;
// This is a factory that provides compaction filter objects which allow
// an application to modify/delete a key-value during background compaction.
@@ -269,7 +272,7 @@ struct ColumnFamilyOptions {
// from a single thread and so does not need to be thread-safe.
//
// Default: nullptr
std::shared_ptr<CompactionFilterFactory> compaction_filter_factory;
std::shared_ptr<CompactionFilterFactory> compaction_filter_factory = nullptr;
// -------------------
// Parameters that affect performance
@@ -290,7 +293,7 @@ struct ColumnFamilyOptions {
// Default: 64MB
//
// Dynamically changeable through SetOptions() API
size_t write_buffer_size;
size_t write_buffer_size = 64 << 20;
// The maximum number of write buffers that are built up in memory.
// The default and the minimum number is 2, so that when 1 write buffer
@@ -303,7 +306,7 @@ struct ColumnFamilyOptions {
// Default: 2
//
// Dynamically changeable through SetOptions() API
int max_write_buffer_number;
int max_write_buffer_number = 2;
// The minimum number of write buffers that will be merged together
// before writing to storage. If set to 1, then
@@ -312,7 +315,7 @@ struct ColumnFamilyOptions {
// files. Also, an in-memory merge may result in writing lesser
// data to storage if there are duplicate records in each of these
// individual write buffers. Default: 1
int min_write_buffer_number_to_merge;
int min_write_buffer_number_to_merge = 1;
// The total maximum number of write buffers to maintain in memory including
// copies of buffers that have already been flushed. Unlike
@@ -338,7 +341,7 @@ struct ColumnFamilyOptions {
// If using a TransactionDB/OptimisticTransactionDB, the default value will
// be set to the value of 'max_write_buffer_number' if it is not explicitly
// set by the user. Otherwise, the default is 0.
int max_write_buffer_number_to_maintain;
int max_write_buffer_number_to_maintain = 0;
// Compress blocks using the specified compression algorithm. This
// parameter can be changed dynamically.
@@ -384,7 +387,7 @@ struct ColumnFamilyOptions {
// levels after base level.
//
// Default: kDisableCompressionOption (Disabled)
CompressionType bottommost_compression;
CompressionType bottommost_compression = kDisableCompressionOption;
// different options for compression algorithms
CompressionOptions compression_opts;
@@ -403,10 +406,10 @@ struct ColumnFamilyOptions {
// 4) prefix(prefix(key)) == prefix(key)
//
// Default: nullptr
std::shared_ptr<const SliceTransform> prefix_extractor;
std::shared_ptr<const SliceTransform> prefix_extractor = nullptr;
// Number of levels for this database
int num_levels;
int num_levels = 7;
// Number of files to trigger level-0 compaction. A value <0 means that
// level-0 compaction will not be triggered by number of files at all.
@@ -414,19 +417,23 @@ struct ColumnFamilyOptions {
// Default: 4
//
// Dynamically changeable through SetOptions() API
int level0_file_num_compaction_trigger;
int level0_file_num_compaction_trigger = 4;
// Soft limit on number of level-0 files. We start slowing down writes at this
// point. A value <0 means that no writing slow down will be triggered by
// number of files in level-0.
//
// Default: 20
//
// Dynamically changeable through SetOptions() API
int level0_slowdown_writes_trigger;
int level0_slowdown_writes_trigger = 20;
// Maximum number of level-0 files. We stop writes at this point.
//
// Default: 36
//
// Dynamically changeable through SetOptions() API
int level0_stop_writes_trigger;
int level0_stop_writes_trigger = 36;
// This does not do anything anymore. Deprecated.
int max_mem_compaction_level;
@@ -443,13 +450,13 @@ struct ColumnFamilyOptions {
// Default: 64MB.
//
// Dynamically changeable through SetOptions() API
uint64_t target_file_size_base;
uint64_t target_file_size_base = 64 * 1048576;
// By default target_file_size_multiplier is 1, which means
// by default files in different levels will have similar size.
//
// Dynamically changeable through SetOptions() API
int target_file_size_multiplier;
int target_file_size_multiplier = 1;
// Control maximum total data size for a level.
// max_bytes_for_level_base is the max total for level-1.
@@ -463,7 +470,7 @@ struct ColumnFamilyOptions {
// Default: 256MB.
//
// Dynamically changeable through SetOptions() API
uint64_t max_bytes_for_level_base;
uint64_t max_bytes_for_level_base = 256 * 1048576;
// If true, RocksDB will pick target size of each level dynamically.
// We will pick a base level b >= 1. L0 will be directly merged into level b,
@@ -522,12 +529,12 @@ struct ColumnFamilyOptions {
// NOTE: this option is experimental
//
// Default: false
bool level_compaction_dynamic_level_bytes;
bool level_compaction_dynamic_level_bytes = false;
// Default: 10.
//
// Dynamically changeable through SetOptions() API
double max_bytes_for_level_multiplier;
double max_bytes_for_level_multiplier = 10;
// Different max-size multipliers for different levels.
// These are multiplied by max_bytes_for_level_multiplier to arrive
@@ -536,14 +543,15 @@ struct ColumnFamilyOptions {
// Default: 1
//
// Dynamically changeable through SetOptions() API
std::vector<int> max_bytes_for_level_multiplier_additional;
std::vector<int> max_bytes_for_level_multiplier_additional =
std::vector<int>(num_levels, 1);
// We try to limit number of bytes in one compaction to be lower than this
// threshold. But it's not guaranteed.
// Value 0 will be sanitized.
//
// Default: result.target_file_size_base * 25
uint64_t max_compaction_bytes;
uint64_t max_compaction_bytes = 0;
// DEPRECATED -- this options is no longer used
// Puts are delayed to options.delayed_write_rate when any level has a
@@ -552,25 +560,25 @@ struct ColumnFamilyOptions {
// Default: 0 (disabled)
//
// Dynamically changeable through SetOptions() API
double soft_rate_limit;
double soft_rate_limit = 0.0;
// DEPRECATED -- this options is no longer used
double hard_rate_limit;
double hard_rate_limit = 0.0;
// All writes will be slowed down to at least delayed_write_rate if estimated
// bytes needed to be compaction exceed this threshold.
//
// Default: 64GB
uint64_t soft_pending_compaction_bytes_limit;
uint64_t soft_pending_compaction_bytes_limit = 64 * 1073741824ull;
// All writes are stopped if estimated bytes needed to be compaction exceed
// this threshold.
//
// Default: 256GB
uint64_t hard_pending_compaction_bytes_limit;
uint64_t hard_pending_compaction_bytes_limit = 256 * 1073741824ull;
// DEPRECATED -- this options is no longer used
unsigned int rate_limit_delay_max_milliseconds;
unsigned int rate_limit_delay_max_milliseconds = 100;
// size of one block in arena memory allocation.
// If <= 0, a proper value is automatically calculated (usually 1/8 of
@@ -587,25 +595,25 @@ struct ColumnFamilyOptions {
// Default: 0
//
// Dynamically changeable through SetOptions() API
size_t arena_block_size;
size_t arena_block_size = 0;
// Disable automatic compactions. Manual compactions can still
// be issued on this column family
//
// Dynamically changeable through SetOptions() API
bool disable_auto_compactions;
bool disable_auto_compactions = false;
// DEPREACTED
// Does not have any effect.
bool purge_redundant_kvs_while_flush;
bool purge_redundant_kvs_while_flush = true;
// The compaction style. Default: kCompactionStyleLevel
CompactionStyle compaction_style;
CompactionStyle compaction_style = kCompactionStyleLevel;
// If level compaction_style = kCompactionStyleLevel, for each level,
// which files are prioritized to be picked to compact.
// Default: kByCompensatedSize
CompactionPri compaction_pri;
CompactionPri compaction_pri = kByCompensatedSize;
// If true, compaction will verify checksum on every read that happens
// as part of compaction
@@ -613,7 +621,7 @@ struct ColumnFamilyOptions {
// Default: true
//
// Dynamically changeable through SetOptions() API
bool verify_checksums_in_compaction;
bool verify_checksums_in_compaction = true;
// The options needed to support Universal Style compactions
CompactionOptionsUniversal compaction_options_universal;
@@ -629,12 +637,13 @@ struct ColumnFamilyOptions {
// Default: 8
//
// Dynamically changeable through SetOptions() API
uint64_t max_sequential_skip_in_iterations;
uint64_t max_sequential_skip_in_iterations = 8;
// This is a factory that provides MemTableRep objects.
// Default: a factory that provides a skip-list-based implementation of
// MemTableRep.
std::shared_ptr<MemTableRepFactory> memtable_factory;
std::shared_ptr<MemTableRepFactory> memtable_factory =
std::shared_ptr<SkipListFactory>(new SkipListFactory);
// This is a factory that provides TableFactory objects.
// Default: a block-based table factory that provides a default
@@ -674,13 +683,13 @@ struct ColumnFamilyOptions {
// * existing_value for that key is a put i.e. kTypeValue
// If inplace_callback function is set, check doc for inplace_callback.
// Default: false.
bool inplace_update_support;
bool inplace_update_support = false;
// Number of locks used for inplace update
// Default: 10000, if inplace_update_support = true, else 0.
//
// Dynamically changeable through SetOptions() API
size_t inplace_update_num_locks;
size_t inplace_update_num_locks = 10000;
// existing_value - pointer to previous value (from both memtable and sst).
// nullptr if key doesn't exist
@@ -722,7 +731,7 @@ struct ColumnFamilyOptions {
UpdateStatus (*inplace_callback)(char* existing_value,
uint32_t* existing_value_size,
Slice delta_value,
std::string* merged_value);
std::string* merged_value) = nullptr;
// if prefix_extractor is set and memtable_prefix_bloom_size_ratio is not 0,
// create prefix bloom for memtable with the size of
@@ -732,7 +741,7 @@ struct ColumnFamilyOptions {
// Default: 0 (disable)
//
// Dynamically changeable through SetOptions() API
double memtable_prefix_bloom_size_ratio;
double memtable_prefix_bloom_size_ratio = 0.0;
// Page size for huge page for the arena used by the memtable. If <=0, it
// won't allocate from huge page but from malloc.
@@ -744,7 +753,7 @@ struct ColumnFamilyOptions {
// malloc.
//
// Dynamically changeable through SetOptions() API
size_t memtable_huge_page_size;
size_t memtable_huge_page_size = 0;
// If non-nullptr, memtable will use the specified function to extract
// prefixes for keys, and for each prefix maintain a hint of insert location
@@ -766,7 +775,7 @@ struct ColumnFamilyOptions {
//
// Default: nullptr (disable)
std::shared_ptr<const SliceTransform>
memtable_insert_with_hint_prefix_extractor;
memtable_insert_with_hint_prefix_extractor = nullptr;
// Control locality of bloom filter probes to improve cache miss rate.
// This option only applies to memtable prefix bloom and plaintable
@@ -774,7 +783,7 @@ struct ColumnFamilyOptions {
// This optimization is turned off when set to 0, and positive number to turn
// it on.
// Default: 0
uint32_t bloom_locality;
uint32_t bloom_locality = 0;
// Maximum number of successive merge operations on a key in the memtable.
//
@@ -787,7 +796,7 @@ struct ColumnFamilyOptions {
// Default: 0 (disabled)
//
// Dynamically changeable through SetOptions() API
size_t max_successive_merges;
size_t max_successive_merges = 0;
// The number of partial merge operands to accumulate before partial
// merge will be performed. Partial merge will not be called
@@ -796,7 +805,7 @@ struct ColumnFamilyOptions {
// If min_partial_merge_operands < 2, then it will be treated as 2.
//
// Default: 2
uint32_t min_partial_merge_operands;
uint32_t min_partial_merge_operands = 2;
// This flag specifies that the implementation should optimize the filters
// mainly for cases where keys are found rather than also optimize for keys
@@ -812,21 +821,21 @@ struct ColumnFamilyOptions {
// to the higher level.
//
// Default: false
bool optimize_filters_for_hits;
bool optimize_filters_for_hits = false;
// After writing every SST file, reopen it and read all the keys.
// Default: false
bool paranoid_file_checks;
bool paranoid_file_checks = false;
// In debug mode, RocksDB run consistency checks on the LSM everytime the LSM
// change (Flush, Compaction, AddFile). These checks are disabled in release
// mode, use this option to enable them in release mode as well.
// Default: false
bool force_consistency_checks;
bool force_consistency_checks = false;
// Measure IO stats in compactions and flushes, if true.
// Default: false
bool report_bg_io_stats;
bool report_bg_io_stats = false;
// Create ColumnFamilyOptions with default values for all fields
ColumnFamilyOptions();
@@ -858,15 +867,15 @@ struct DBOptions {
// If true, the database will be created if it is missing.
// Default: false
bool create_if_missing;
bool create_if_missing = false;
// If true, missing column families will be automatically created.
// Default: false
bool create_missing_column_families;
bool create_missing_column_families = false;
// If true, an error is raised if the database already exists.
// Default: false
bool error_if_exists;
bool error_if_exists = false;
// If true, RocksDB will aggressively check consistency of the data.
// Also, if any of the writes to the database fails (Put, Delete, Merge,
@@ -874,18 +883,18 @@ struct DBOptions {
// Write operations.
// In most cases you want this to be set to true.
// Default: true
bool paranoid_checks;
bool paranoid_checks = true;
// Use the specified object to interact with the environment,
// e.g. to read/write files, schedule background work, etc.
// Default: Env::Default()
Env* env;
Env* env = Env::Default();
// Use to control write rate of flush and compaction. Flush has higher
// priority than compaction. Rate limiting is disabled if nullptr.
// If rate limiter is enabled, bytes_per_sync is set to 1MB by default.
// Default: nullptr
std::shared_ptr<RateLimiter> rate_limiter;
std::shared_ptr<RateLimiter> rate_limiter = nullptr;
// Use to track SST files and control their file deletion rate.
//
@@ -901,15 +910,19 @@ struct DBOptions {
// first db_path (db_name if db_paths is empty).
//
// Default: nullptr
std::shared_ptr<SstFileManager> sst_file_manager;
std::shared_ptr<SstFileManager> sst_file_manager = nullptr;
// Any internal progress/error information generated by the db will
// be written to info_log if it is non-nullptr, or to a file stored
// in the same directory as the DB contents if info_log is nullptr.
// Default: nullptr
std::shared_ptr<Logger> info_log;
std::shared_ptr<Logger> info_log = nullptr;
InfoLogLevel info_log_level;
#ifdef NDEBUG
InfoLogLevel info_log_level = INFO_LEVEL;
#else
InfoLogLevel info_log_level = DEBUG_LEVEL;
#endif // NDEBUG
// Number of open files that can be used by the DB. You may need to
// increase this if your database has a large working set. Value -1 means
@@ -917,12 +930,12 @@ struct DBOptions {
// on target_file_size_base and target_file_size_multiplier for level-based
// compaction. For universal-style compaction, you can usually set it to -1.
// Default: -1
int max_open_files;
int max_open_files = -1;
// If max_open_files is -1, DB will open all files on DB::Open(). You can
// use this option to increase the number of threads used to open the files.
// Default: 16
int max_file_opening_threads;
int max_file_opening_threads = 16;
// Once write-ahead logs exceed this size, we will start forcing the flush of
// column families whose memtables are backed by the oldest live WAL file
@@ -930,12 +943,10 @@ struct DBOptions {
// (default), we will dynamically choose the WAL size limit to be
// [sum of all write_buffer_size * max_write_buffer_number] * 4
// Default: 0
uint64_t max_total_wal_size;
uint64_t max_total_wal_size = 0;
// If non-null, then we should collect metrics about database operations
// Statistics objects should not be shared between DB instances as
// it does not use any locks to prevent concurrent updates.
std::shared_ptr<Statistics> statistics;
std::shared_ptr<Statistics> statistics = nullptr;
// If true, then the contents of manifest and data files are not synced
// to stable storage. Their contents remain in the OS buffers till the
@@ -943,14 +954,14 @@ struct DBOptions {
// of data. Once the bulk-loading is complete, please issue a
// sync to the OS to flush all dirty buffers to stable storage.
// Default: false
bool disableDataSync;
bool disableDataSync = false;
// If true, then every store to stable storage will issue a fsync.
// If false, then every store to stable storage will issue a fdatasync.
// This parameter should be set to true while storing data to
// filesystem like ext3 that can lose files after a reboot.
// Default: false
bool use_fsync;
bool use_fsync = false;
// A list of paths where SST files can be put into, with its target size.
// Newer data is placed into paths specified earlier in the vector while
@@ -983,7 +994,7 @@ struct DBOptions {
// If it is non empty, the log files will be in the specified dir,
// and the db data dir's absolute path will be used as the log file
// name's prefix.
std::string db_log_dir;
std::string db_log_dir = "";
// This specifies the absolute dir path for write-ahead logs (WAL).
// If it is empty, the log files will be in the same dir as data,
@@ -991,19 +1002,19 @@ struct DBOptions {
// If it is non empty, the log files will be in kept the specified dir.
// When destroying the db,
// all log files in wal_dir and the dir itself is deleted
std::string wal_dir;
std::string wal_dir = "";
// The periodicity when obsolete files get deleted. The default
// value is 6 hours. The files that get out of scope by compaction
// process will still get automatically delete on every compaction,
// regardless of this setting
uint64_t delete_obsolete_files_period_micros;
uint64_t delete_obsolete_files_period_micros = 6ULL * 60 * 60 * 1000000;
// Suggested number of concurrent background compaction jobs, submitted to
// the default LOW priority thread pool.
//
// Default: 1
int base_background_compactions;
int base_background_compactions = 1;
// Maximum number of concurrent background compaction jobs, submitted to
// the default LOW priority thread pool.
@@ -1016,13 +1027,13 @@ struct DBOptions {
// LOW priority thread pool. For more information, see
// Env::SetBackgroundThreads
// Default: 1
int max_background_compactions;
int max_background_compactions = 1;
// This value represents the maximum number of threads that will
// concurrently perform a compaction job by breaking it into multiple,
// smaller ones that are run simultaneously.
// Default: 1 (i.e. no subcompactions)
uint32_t max_subcompactions;
uint32_t max_subcompactions = 1;
// Maximum number of concurrent background memtable flush jobs, submitted to
// the HIGH priority thread pool.
@@ -1039,24 +1050,24 @@ struct DBOptions {
// HIGH priority thread pool. For more information, see
// Env::SetBackgroundThreads
// Default: 1
int max_background_flushes;
int max_background_flushes = 1;
// Specify the maximal size of the info log file. If the log file
// is larger than `max_log_file_size`, a new info log file will
// be created.
// If max_log_file_size == 0, all logs will be written to one
// log file.
size_t max_log_file_size;
size_t max_log_file_size = 0;
// Time for the info log file to roll (in seconds).
// If specified with non-zero value, log file will be rolled
// if it has been active longer than `log_file_time_to_roll`.
// Default: 0 (disabled)
size_t log_file_time_to_roll;
size_t log_file_time_to_roll = 0;
// Maximal info log files to be kept.
// Default: 1000
size_t keep_log_file_num;
size_t keep_log_file_num = 1000;
// Recycle log files.
// If non-zero, we will reuse previously written log files for new
@@ -1066,15 +1077,15 @@ struct DBOptions {
// allocated and fdatasync does not need to update the inode after
// each write.
// Default: 0
size_t recycle_log_file_num;
size_t recycle_log_file_num = 0;
// manifest file is rolled over on reaching this limit.
// The older manifest file be deleted.
// The default value is MAX_INT so that roll-over does not take place.
uint64_t max_manifest_file_size;
uint64_t max_manifest_file_size = std::numeric_limits<uint64_t>::max();
// Number of shards used for table cache.
int table_cache_numshardbits;
int table_cache_numshardbits = 6;
// DEPRECATED
// int table_cache_remove_scan_count_limit;
@@ -1091,22 +1102,22 @@ struct DBOptions {
// are older than WAL_ttl_seconds will be deleted.
// 4. If both are not 0, WAL files will be checked every 10 min and both
// checks will be performed with ttl being first.
uint64_t WAL_ttl_seconds;
uint64_t WAL_size_limit_MB;
uint64_t WAL_ttl_seconds = 0;
uint64_t WAL_size_limit_MB = 0;
// Number of bytes to preallocate (via fallocate) the manifest
// files. Default is 4mb, which is reasonable to reduce random IO
// as well as prevent overallocation for mounts that preallocate
// large amounts of data (such as xfs's allocsize option).
size_t manifest_preallocation_size;
size_t manifest_preallocation_size = 4 * 1024 * 1024;
// Allow the OS to mmap file for reading sst tables. Default: false
bool allow_mmap_reads;
bool allow_mmap_reads = false;
// Allow the OS to mmap file for writing.
// DB::SyncWAL() only works if this is set to false.
// Default: false
bool allow_mmap_writes;
bool allow_mmap_writes = false;
// Enable direct I/O mode for read/write
// they may or may not improve performance depending on the use case
@@ -1118,29 +1129,29 @@ struct DBOptions {
// Use O_DIRECT for reading file
// Default: false
bool use_direct_reads;
bool use_direct_reads = false;
// Use O_DIRECT for writing file
// Default: false
bool use_direct_writes;
bool use_direct_writes = false;
// If false, fallocate() calls are bypassed
bool allow_fallocate;
bool allow_fallocate = true;
// Disable child process inherit open files. Default: true
bool is_fd_close_on_exec;
bool is_fd_close_on_exec = true;
// DEPRECATED -- this options is no longer used
bool skip_log_error_on_recovery;
bool skip_log_error_on_recovery = false;
// if not zero, dump rocksdb.stats to LOG every stats_dump_period_sec
// Default: 600 (10 min)
unsigned int stats_dump_period_sec;
unsigned int stats_dump_period_sec = 600;
// If set true, will hint the underlying file system that the file
// access pattern is random, when a sst file is opened.
// Default: true
bool advise_random_on_open;
bool advise_random_on_open = true;
// Amount of data to build up in memtables across all column
// families before writing to disk.
@@ -1152,7 +1163,7 @@ struct DBOptions {
// to enable it.
//
// Default: 0 (disabled)
size_t db_write_buffer_size;
size_t db_write_buffer_size = 0;
// The memory usage of memtable will report to this object. The same object
// can be passed into multiple DBs and it will track the sum of size of all
@@ -1168,7 +1179,7 @@ struct DBOptions {
// to enable it.
//
// Default: null
std::shared_ptr<WriteBufferManager> write_buffer_manager;
std::shared_ptr<WriteBufferManager> write_buffer_manager = nullptr;
// Specify the file access pattern once a compaction is started.
// It will be applied to all input files of a compaction.
@@ -1179,7 +1190,7 @@ struct DBOptions {
SEQUENTIAL,
WILLNEED
};
AccessHint access_hint_on_compaction_start;
AccessHint access_hint_on_compaction_start = NORMAL;
// If true, always create a new file descriptor and new table reader
// for compaction inputs. Turn this parameter on may introduce extra
@@ -1191,7 +1202,7 @@ struct DBOptions {
// for this mode if using block-based table.
//
// Default: false
bool new_table_reader_for_compaction_inputs;
bool new_table_reader_for_compaction_inputs = false;
// If non-zero, we perform bigger reads when doing compaction. If you're
// running RocksDB on spinning disks, you should set this to at least 2MB.
@@ -1201,7 +1212,7 @@ struct DBOptions {
// true.
//
// Default: 0
size_t compaction_readahead_size;
size_t compaction_readahead_size = 0;
// This is a maximum buffer size that is used by WinMmapReadableFile in
// unbuffered disk I/O mode. We need to maintain an aligned buffer for
@@ -1218,14 +1229,14 @@ struct DBOptions {
//
// Special value: 0 - means do not maintain per instance buffer. Allocate
// per request buffer and avoid locking.
size_t random_access_max_buffer_size;
size_t random_access_max_buffer_size = 1024 * 1024;
// This is the maximum buffer size that is used by WritableFileWriter.
// On Windows, we need to maintain an aligned buffer for writes.
// We allow the buffer to grow until it's size hits the limit.
//
// Default: 1024 * 1024 (1 MB)
size_t writable_file_max_buffer_size;
size_t writable_file_max_buffer_size = 1024 * 1024;
// Use adaptive mutex, which spins in the user space before resorting
@@ -1233,7 +1244,7 @@ struct DBOptions {
// heavily contended. However, if the mutex is hot, we could end up
// wasting spin time.
// Default: false
bool use_adaptive_mutex;
bool use_adaptive_mutex = false;
// Create DBOptions with default values for all fields
DBOptions();
@@ -1254,11 +1265,11 @@ struct DBOptions {
// to 1MB.
//
// This option applies to table files
uint64_t bytes_per_sync;
uint64_t bytes_per_sync = 0;
// Same as bytes_per_sync, but applies to WAL files
// Default: 0, turned off
uint64_t wal_bytes_per_sync;
uint64_t wal_bytes_per_sync = 0;
// A vector of EventListeners which call-back functions will be called
// when specific RocksDB event happens.
@@ -1268,7 +1279,7 @@ struct DBOptions {
// be tracked and available via GetThreadList() API.
//
// Default: false
bool enable_thread_tracking;
bool enable_thread_tracking = false;
// The limited write rate to DB if soft_pending_compaction_bytes_limit or
// level0_slowdown_writes_trigger is triggered, or we are writing to the
@@ -1278,8 +1289,8 @@ struct DBOptions {
// gets behind further.
// Unit: byte per second.
//
// Default: 2MB/s
uint64_t delayed_write_rate;
// Default: 16MB/s
uint64_t delayed_write_rate = 16 * 1024U * 1024U;
// If true, allow multi-writers to update mem tables in parallel.
// Only some memtable_factory-s support concurrent writes; currently it
@@ -1289,7 +1300,7 @@ struct DBOptions {
// if you are going to use this feature.
//
// Default: true
bool allow_concurrent_memtable_write;
bool allow_concurrent_memtable_write = true;
// If true, threads synchronizing with the write batch group leader will
// wait for up to write_thread_max_yield_usec before blocking on a mutex.
@@ -1297,7 +1308,7 @@ struct DBOptions {
// regardless of whether allow_concurrent_memtable_write is enabled.
//
// Default: true
bool enable_write_thread_adaptive_yield;
bool enable_write_thread_adaptive_yield = true;
// The maximum number of microseconds that a write operation will use
// a yielding spin loop to coordinate with other write threads before
@@ -1306,7 +1317,7 @@ struct DBOptions {
// throughput at the expense of increased CPU usage.
//
// Default: 100
uint64_t write_thread_max_yield_usec;
uint64_t write_thread_max_yield_usec = 100;
// The latency in microseconds after which a std::this_thread::yield
// call (sched_yield on Linux) is considered to be a signal that
@@ -1316,7 +1327,7 @@ struct DBOptions {
// involuntary context switches.
//
// Default: 3
uint64_t write_thread_slow_yield_usec;
uint64_t write_thread_slow_yield_usec = 3;
// If true, then DB::Open() will not update the statistics used to optimize
// compaction decision by loading table properties from many files.
@@ -1324,11 +1335,11 @@ struct DBOptions {
// disk environment.
//
// Default: false
bool skip_stats_update_on_db_open;
bool skip_stats_update_on_db_open = false;
// Recovery mode to control the consistency while replaying WAL
// Default: kPointInTimeRecovery
WALRecoveryMode wal_recovery_mode;
WALRecoveryMode wal_recovery_mode = WALRecoveryMode::kPointInTimeRecovery;
// if set to false then recovery will fail when a prepared
// transaction is encountered in the WAL
@@ -1337,7 +1348,7 @@ struct DBOptions {
// A global cache for table-level rows.
// Default: nullptr (disabled)
// Not supported in ROCKSDB_LITE mode!
std::shared_ptr<Cache> row_cache;
std::shared_ptr<Cache> row_cache = nullptr;
#ifndef ROCKSDB_LITE
// A filter object supplied to be invoked while processing write-ahead-logs
@@ -1345,7 +1356,7 @@ struct DBOptions {
// records, ignoring a particular record or skipping replay.
// The filter is invoked at startup and is invoked from a single-thread
// currently.
WalFilter* wal_filter;
WalFilter* wal_filter = nullptr;
#endif // ROCKSDB_LITE
// If true, then DB::Open / CreateColumnFamily / DropColumnFamily
@@ -1353,12 +1364,12 @@ struct DBOptions {
// persisted.
//
// DEFAULT: false
bool fail_if_options_file_error;
bool fail_if_options_file_error = false;
// If true, then print malloc stats together with rocksdb.stats
// when printing to LOG.
// DEFAULT: false
bool dump_malloc_stats;
bool dump_malloc_stats = false;
// By default RocksDB replay WAL logs and flush them on DB open, which may
// create very small SST files. If this option is enabled, RocksDB will try
@@ -1367,7 +1378,7 @@ struct DBOptions {
// have logs to recover from.
//
// DEFAULT: false
bool avoid_flush_during_recovery;
bool avoid_flush_during_recovery = false;
// By default RocksDB will flush all memtables on DB close if there are
// unpersisted data (i.e. with WAL disabled) The flush can be skip to speedup
@@ -1376,7 +1387,7 @@ struct DBOptions {
// DEFAULT: false
//
// Dynamically changeable through SetDBOptions() API.
bool avoid_flush_during_shutdown;
bool avoid_flush_during_shutdown = false;
};
// Options to control the behavior of a database (passed to DB::Open)
@@ -1508,7 +1519,7 @@ struct ReadOptions {
// used in the table. Some table format (e.g. plain table) may not support
// this option.
// If true when calling Get(), we also skip prefix bloom when reading from
// block based table. It provides a way to read exisiting data after
// block based table. It provides a way to read existing data after
// changing implementation of prefix extractor.
bool total_order_seek;
+2 -2
View File
@@ -68,13 +68,13 @@ class SstFileManager {
// this value is set to 1024 (1 Kb / sec) and we deleted a file of size 4 Kb
// in 1 second, we will wait for another 3 seconds before we delete other
// files, Set to 0 to disable deletion rate limiting.
// @param delete_exisitng_trash: If set to true, the newly created
// @param delete_existing_trash: If set to true, the newly created
// SstFileManager will delete files that already exist in trash_dir.
// @param status: If not nullptr, status will contain any errors that happened
// during creating the missing trash_dir or deleting existing files in trash.
extern SstFileManager* NewSstFileManager(
Env* env, std::shared_ptr<Logger> info_log = nullptr,
std::string trash_dir = "", int64_t rate_bytes_per_sec = 0,
bool delete_exisitng_trash = true, Status* status = nullptr);
bool delete_existing_trash = true, Status* status = nullptr);
} // namespace rocksdb
+10
View File
@@ -86,6 +86,12 @@ struct BlockBasedTableOptions {
// The hash index, if enabled, will do the hash lookup when
// `Options.prefix_extractor` is provided.
kHashSearch,
// TODO(myabandeh): this feature is in experimental phase and shall not be
// used in production; either remove the feature or remove this comment if
// it is ready to be used in production.
// A two-level index implementation. Both levels are binary search indexes.
kTwoLevelIndexSearch,
};
IndexType index_type = kBinarySearch;
@@ -138,6 +144,10 @@ struct BlockBasedTableOptions {
// Same as block_restart_interval but used for the index block.
int index_block_restart_interval = 1;
// Number of index keys per partition of indexes in a multi-level index
// i.e., the number of data blocks covered by each index partition
uint64_t index_per_partition = 1024;
// Use delta encoding to compress keys in blocks.
// ReadOptions::pin_data requires this option to be disabled.
//
+19
View File
@@ -8,6 +8,8 @@
// found in the LICENSE file. See the AUTHORS file for names of contributors.
#pragma once
#include <functional>
namespace rocksdb {
/*
@@ -20,6 +22,8 @@ class ThreadPool {
virtual ~ThreadPool() {}
// Wait for all threads to finish.
// Discard those threads that did not start
// executing
virtual void JoinAllThreads() = 0;
// Set the number of background threads that will be executing the
@@ -28,6 +32,21 @@ class ThreadPool {
// Get the number of jobs scheduled in the ThreadPool queue.
virtual unsigned int GetQueueLen() const = 0;
// Waits for all jobs to complete those
// that already started running and those that did not
// start yet. This ensures that everything that was thrown
// on the TP runs even though
// we may not have specified enough threads for the amount
// of jobs
virtual void WaitForJobsAndJoinAllThreads() = 0;
// Submit a fire and forget jobs
// This allows to submit the same job multiple times
virtual void SubmitJob(const std::function<void()>&) = 0;
// This moves the function in for efficiency
virtual void SubmitJob(std::function<void()>&&) = 0;
};
// NewThreadPool() is a function that could be used to create a ThreadPool
-45
View File
@@ -1,45 +0,0 @@
// Copyright (c) 2016-present, Facebook, Inc. All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
#pragma once
#ifndef ROCKSDB_LITE
#include <functional>
#include <memory>
#include <string>
#include "rocksdb/env.h"
namespace rocksdb {
// Returns a new Env when called with a URI string. Populates the unique_ptr
// argument if granting ownership to caller.
typedef std::function<Env*(const std::string&, std::unique_ptr<Env>*)>
EnvFactoryFunc;
// Creates a new Env using the registered factory function corresponding to a
// prefix of uri.
//
// If no prefixes match, returns nullptr. If multiple prefixes match, the
// factory function used is unspecified.
//
// Populates env_guard with result pointer if caller is granted ownership.
Env* NewEnvFromUri(const std::string& uri, std::unique_ptr<Env>* env_guard);
// To register an Env factory function, initialize an EnvRegistrar object with
// static storage duration. For example:
//
// static EnvRegistrar hdfs_reg("hdfs://", &CreateHdfsEnv);
//
// Then, calling NewEnvFromUri("hdfs://some_path", ...) will use CreateHdfsEnv
// to make a new Env.
class EnvRegistrar {
public:
explicit EnvRegistrar(std::string uri_prefix, EnvFactoryFunc env_factory);
};
} // namespace rocksdb
#endif // ROCKSDB_LITE
@@ -0,0 +1,90 @@
// Copyright (c) 2016-present, Facebook, Inc. All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
#pragma once
#ifndef ROCKSDB_LITE
#include <functional>
#include <memory>
#include <regex>
#include <string>
#include <vector>
#include "rocksdb/env.h"
namespace rocksdb {
// Creates a new T using the factory function that was registered with a pattern
// that matches the provided "target" string according to std::regex_match.
//
// If no registered functions match, returns nullptr. If multiple functions
// match, the factory function used is unspecified.
//
// Populates res_guard with result pointer if caller is granted ownership.
template <typename T>
T* NewCustomObject(const std::string& target, std::unique_ptr<T>* res_guard);
// Returns a new T when called with a string. Populates the unique_ptr argument
// if granting ownership to caller.
template <typename T>
using FactoryFunc = std::function<T*(const std::string&, std::unique_ptr<T>*)>;
// To register a factory function for a type T, initialize a Registrar<T> object
// with static storage duration. For example:
//
// static Registrar<Env> hdfs_reg("hdfs://.*", &CreateHdfsEnv);
//
// Then, calling NewCustomObject<Env>("hdfs://some_path", ...) will match the
// regex provided above, so it returns the result of invoking CreateHdfsEnv.
template <typename T>
class Registrar {
public:
explicit Registrar(std::string pattern, FactoryFunc<T> factory);
};
// Implementation details follow.
namespace internal {
template <typename T>
struct RegistryEntry {
std::regex pattern;
FactoryFunc<T> factory;
};
template <typename T>
struct Registry {
static Registry* Get() {
static Registry<T> instance;
return &instance;
}
std::vector<RegistryEntry<T>> entries;
private:
Registry() = default;
};
} // namespace internal
template <typename T>
T* NewCustomObject(const std::string& target, std::unique_ptr<T>* res_guard) {
res_guard->reset();
for (const auto& entry : internal::Registry<T>::Get()->entries) {
if (std::regex_match(target, entry.pattern)) {
return entry.factory(target, res_guard);
}
}
return nullptr;
}
template <typename T>
Registrar<T>::Registrar(std::string pattern, FactoryFunc<T> factory) {
internal::Registry<T>::Get()->entries.emplace_back(internal::RegistryEntry<T>{
std::regex(std::move(pattern)), std::move(factory)});
}
} // namespace rocksdb
#endif // ROCKSDB_LITE
+11 -2
View File
@@ -161,9 +161,18 @@ class StackableDB : public DB {
using DB::GetApproximateSizes;
virtual void GetApproximateSizes(ColumnFamilyHandle* column_family,
const Range* r, int n, uint64_t* sizes,
bool include_memtable = false) override {
uint8_t include_flags
= INCLUDE_FILES) override {
return db_->GetApproximateSizes(column_family, r, n, sizes,
include_memtable);
include_flags);
}
using DB::GetApproximateMemTableStats;
virtual void GetApproximateMemTableStats(ColumnFamilyHandle* column_family,
const Range& range,
uint64_t* const count,
uint64_t* const size) override {
return db_->GetApproximateMemTableStats(column_family, range, count, size);
}
using DB::CompactRange;
+2 -2
View File
@@ -5,8 +5,8 @@
#pragma once
#define ROCKSDB_MAJOR 5
#define ROCKSDB_MINOR 0
#define ROCKSDB_PATCH 0
#define ROCKSDB_MINOR 2
#define ROCKSDB_PATCH 1
// Do not use these. We made the mistake of declaring macros starting with
// double underscore. Now we have to live with our choice. We'll deprecate these
@@ -14,71 +14,60 @@ public abstract class AbstractWriteBatch extends RocksObject
@Override
public int count() {
assert (isOwningHandle());
return count0(nativeHandle_);
}
@Override
public void put(byte[] key, byte[] value) {
assert (isOwningHandle());
put(nativeHandle_, key, key.length, value, value.length);
}
@Override
public void put(ColumnFamilyHandle columnFamilyHandle, byte[] key,
byte[] value) {
assert (isOwningHandle());
put(nativeHandle_, key, key.length, value, value.length,
columnFamilyHandle.nativeHandle_);
}
@Override
public void merge(byte[] key, byte[] value) {
assert (isOwningHandle());
merge(nativeHandle_, key, key.length, value, value.length);
}
@Override
public void merge(ColumnFamilyHandle columnFamilyHandle, byte[] key,
byte[] value) {
assert (isOwningHandle());
merge(nativeHandle_, key, key.length, value, value.length,
columnFamilyHandle.nativeHandle_);
}
@Override
public void remove(byte[] key) {
assert (isOwningHandle());
remove(nativeHandle_, key, key.length);
}
@Override
public void remove(ColumnFamilyHandle columnFamilyHandle, byte[] key) {
assert (isOwningHandle());
remove(nativeHandle_, key, key.length, columnFamilyHandle.nativeHandle_);
}
@Override
public void putLogData(byte[] blob) {
assert (isOwningHandle());
putLogData(nativeHandle_, blob, blob.length);
}
@Override
public void clear() {
assert (isOwningHandle());
clear0(nativeHandle_);
}
@Override
public void setSavePoint() {
assert (isOwningHandle());
setSavePoint0(nativeHandle_);
}
@Override
public void rollbackToSavePoint() throws RocksDBException {
assert (isOwningHandle());
rollbackToSavePoint0(nativeHandle_);
}
@@ -18,7 +18,11 @@ public enum IndexType {
* The hash index, if enabled, will do the hash lookup when
* {@code Options.prefix_extractor} is provided.
*/
kHashSearch((byte) 1);
kHashSearch((byte) 1),
/**
* A two-level index implementation. Both levels are binary search indexes.
*/
kTwoLevelIndexSearch((byte) 2);
/**
* Returns the byte value of the enumerations value
@@ -76,7 +76,7 @@ public class TransactionLogIterator extends RocksObject {
public BatchResult(final long sequenceNumber,
final long nativeHandle) {
sequenceNumber_ = sequenceNumber;
writeBatch_ = new WriteBatch(nativeHandle);
writeBatch_ = new WriteBatch(nativeHandle, true);
}
/**
+13 -1
View File
@@ -59,8 +59,20 @@ public class WriteBatch extends AbstractWriteBatch {
* @param nativeHandle address of native instance.
*/
WriteBatch(final long nativeHandle) {
this(nativeHandle, false);
}
/**
* <p>Private WriteBatch constructor which is used to construct
* WriteBatch instances. </p>
*
* @param nativeHandle address of native instance.
* @param owningNativeHandle whether to own this reference from the C++ side or not
*/
WriteBatch(final long nativeHandle, final boolean owningNativeHandle) {
super(nativeHandle);
disOwnNativeHandle();
if(!owningNativeHandle)
disOwnNativeHandle();
}
@Override protected final native void disposeInternal(final long handle);
@@ -95,7 +95,7 @@ public class BlockBasedTableConfigTest {
@Test
public void indexType() {
BlockBasedTableConfig blockBasedTableConfig = new BlockBasedTableConfig();
assertThat(IndexType.values().length).isEqualTo(2);
assertThat(IndexType.values().length).isEqualTo(3);
blockBasedTableConfig.setIndexType(IndexType.kHashSearch);
assertThat(blockBasedTableConfig.indexType().equals(
IndexType.kHashSearch));
+3
View File
@@ -11,6 +11,7 @@
#pragma once
#include <thread>
// size_t printf formatting named in the manner of C99 standard formatting
// strings such as PRIu64
// in fact, we could use that one
@@ -156,6 +157,8 @@ class CondVar {
Mutex* mu_;
};
using Thread = std::thread;
static inline void AsmVolatilePause() {
#if defined(__i386__) || defined(__x86_64__)
asm volatile("pause");
+10 -2
View File
@@ -8,6 +8,7 @@
// found in the LICENSE file. See the AUTHORS file for names of contributors.
#include "port/win/env_win.h"
#include "port/win/win_thread.h"
#include <algorithm>
#include <ctime>
#include <thread>
@@ -119,13 +120,20 @@ Status WinEnvIO::NewSequentialFile(const std::string& fname,
// while they are still open with another handle. For that reason we
// allow share_write and delete(allows rename).
HANDLE hFile = INVALID_HANDLE_VALUE;
DWORD fileFlags = FILE_ATTRIBUTE_READONLY;
if (options.use_direct_reads && !options.use_mmap_reads) {
fileFlags |= FILE_FLAG_NO_BUFFERING;
}
{
IOSTATS_TIMER_GUARD(open_nanos);
hFile = CreateFileA(
fname.c_str(), GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, // Original fopen mode is "rb"
FILE_ATTRIBUTE_NORMAL, NULL);
fileFlags, NULL);
}
if (INVALID_HANDLE_VALUE == hFile) {
@@ -830,7 +838,7 @@ void WinEnvThreads::StartThread(void(*function)(void* arg), void* arg) {
state->arg = arg;
try {
std::thread th(&StartThreadWrapper, state.get());
rocksdb::port::WindowsThread th(&StartThreadWrapper, state.get());
state.release();
std::lock_guard<std::mutex> lg(mu_);
+13 -3
View File
@@ -16,11 +16,21 @@
#pragma once
#include "port/win/win_thread.h"
#include <rocksdb/env.h>
#include "util/threadpool_imp.h"
#include <stdint.h>
#include <Windows.h>
#include <mutex>
#include <vector>
#include <string>
#undef GetCurrentTime
#undef DeleteFile
#undef GetTickCount
namespace rocksdb {
namespace port {
@@ -64,7 +74,7 @@ private:
Env* hosted_env_;
mutable std::mutex mu_;
std::vector<ThreadPoolImpl> thread_pools_;
std::vector<std::thread> threads_to_join_;
std::vector<WindowsThread> threads_to_join_;
};
@@ -281,5 +291,5 @@ private:
WinEnvThreads winenv_threads_;
};
}
}
} // namespace port
} // namespace rocksdb
+40
View File
@@ -556,6 +556,7 @@ WinSequentialFile::~WinSequentialFile() {
}
Status WinSequentialFile::Read(size_t n, Slice* result, char* scratch) {
assert(result != nullptr && !WinFileData::use_direct_io());
Status s;
size_t r = 0;
@@ -580,6 +581,41 @@ Status WinSequentialFile::Read(size_t n, Slice* result, char* scratch) {
return s;
}
SSIZE_T WinSequentialFile::PositionedReadInternal(char* src, size_t numBytes,
uint64_t offset) const {
return pread(GetFileHandle(), src, numBytes, offset);
}
Status WinSequentialFile::PositionedRead(uint64_t offset, size_t n, Slice* result,
char* scratch) {
Status s;
assert(WinFileData::use_direct_io());
// Windows ReadFile API accepts a DWORD.
// While it is possible to read in a loop if n is > UINT_MAX
// it is a highly unlikely case.
if (n > UINT_MAX) {
return IOErrorFromWindowsError(GetName(), ERROR_INVALID_PARAMETER);
}
auto r = PositionedReadInternal(scratch, n, offset);
if (r < 0) {
auto lastError = GetLastError();
// Posix impl wants to treat reads from beyond
// of the file as OK.
if (lastError != ERROR_HANDLE_EOF) {
s = IOErrorFromWindowsError(GetName(), lastError);
}
}
*result = Slice(scratch, (r < 0) ? 0 : size_t(r));
return s;
}
Status WinSequentialFile::Skip(uint64_t n) {
// Can't handle more than signed max as SetFilePointerEx accepts a signed 64-bit
// integer. As such it is a highly unlikley case to have n so large.
@@ -855,6 +891,10 @@ size_t WinRandomAccessFile::GetUniqueId(char* id, size_t max_size) const {
return GetUniqueIdFromFile(GetFileHandle(), id, max_size);
}
size_t WinRandomAccessFile::GetRequiredBufferAlignment() const {
return GetAlignment();
}
/////////////////////////////////////////////////////////////////////////////
// WinWritableImpl
//
+46 -30
View File
@@ -101,6 +101,32 @@ class WinFileData {
WinFileData& operator=(const WinFileData&) = delete;
};
class WinSequentialFile : protected WinFileData, public SequentialFile {
// Override for behavior change when creating a custom env
virtual SSIZE_T PositionedReadInternal(char* src, size_t numBytes,
uint64_t offset) const;
public:
WinSequentialFile(const std::string& fname, HANDLE f,
const EnvOptions& options);
~WinSequentialFile();
WinSequentialFile(const WinSequentialFile&) = delete;
WinSequentialFile& operator=(const WinSequentialFile&) = delete;
virtual Status Read(size_t n, Slice* result, char* scratch) override;
virtual Status PositionedRead(uint64_t offset, size_t n, Slice* result,
char* scratch) override;
virtual Status Skip(uint64_t n) override;
virtual Status InvalidateCache(size_t offset, size_t length) override;
virtual bool use_direct_io() const override { return WinFileData::use_direct_io(); }
};
// mmap() based random-access
class WinMmapReadableFile : private WinFileData, public RandomAccessFile {
HANDLE hMap_;
@@ -208,23 +234,6 @@ class WinMmapFile : private WinFileData, public WritableFile {
virtual size_t GetUniqueId(char* id, size_t max_size) const override;
};
class WinSequentialFile : private WinFileData, public SequentialFile {
public:
WinSequentialFile(const std::string& fname, HANDLE f,
const EnvOptions& options);
~WinSequentialFile();
WinSequentialFile(const WinSequentialFile&) = delete;
WinSequentialFile& operator=(const WinSequentialFile&) = delete;
virtual Status Read(size_t n, Slice* result, char* scratch) override;
virtual Status Skip(uint64_t n) override;
virtual Status InvalidateCache(size_t offset, size_t length) override;
};
class WinRandomAccessImpl {
protected:
WinFileData* file_base_;
@@ -281,14 +290,17 @@ class WinRandomAccessImpl {
virtual ~WinRandomAccessImpl() {}
public:
WinRandomAccessImpl(const WinRandomAccessImpl&) = delete;
WinRandomAccessImpl& operator=(const WinRandomAccessImpl&) = delete;
Status ReadImpl(uint64_t offset, size_t n, Slice* result,
char* scratch) const;
void HintImpl(RandomAccessFile::AccessPattern pattern);
size_t GetAlignment() const { return buffer_.Alignment(); }
public:
WinRandomAccessImpl(const WinRandomAccessImpl&) = delete;
WinRandomAccessImpl& operator=(const WinRandomAccessImpl&) = delete;
};
// pread() based random-access
@@ -303,18 +315,22 @@ class WinRandomAccessFile
~WinRandomAccessFile();
virtual void EnableReadAhead() override;
virtual Status Read(uint64_t offset, size_t n, Slice* result,
char* scratch) const override;
virtual bool ShouldForwardRawRequest() const override;
virtual void EnableReadAhead() override;
virtual size_t GetUniqueId(char* id, size_t max_size) const override;
virtual void Hint(AccessPattern pattern) override;
virtual bool use_direct_io() const override { return WinFileData::use_direct_io(); }
virtual Status InvalidateCache(size_t offset, size_t length) override;
virtual size_t GetUniqueId(char* id, size_t max_size) const override;
virtual size_t GetRequiredBufferAlignment() const override;
};
// This is a sequential write class. It has been mimicked (as others) after
@@ -382,12 +398,6 @@ class WinWritableFile : private WinFileData,
~WinWritableFile();
// Indicates if the class makes use of direct I/O
// Use PositionedAppend
virtual bool use_direct_io() const override;
virtual size_t GetRequiredBufferAlignment() const override;
virtual Status Append(const Slice& data) override;
// Requires that the data is aligned as specified by
@@ -408,6 +418,12 @@ class WinWritableFile : private WinFileData,
virtual Status Fsync() override;
// Indicates if the class makes use of direct I/O
// Use PositionedAppend
virtual bool use_direct_io() const override;
virtual size_t GetRequiredBufferAlignment() const override;
virtual uint64_t GetFileSize() override;
virtual Status Allocate(uint64_t offset, uint64_t len) override;
+5
View File
@@ -30,6 +30,8 @@
#include <stdint.h>
#include "port/win/win_thread.h"
#include "rocksdb/options.h"
#undef min
@@ -206,6 +208,9 @@ class CondVar {
Mutex* mu_;
};
// Wrapper around the platform efficient
// or otherwise preferrable implementation
using Thread = WindowsThread;
// OnceInit type helps emulate
// Posix semantics with initialization
+166
View File
@@ -0,0 +1,166 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
#include "port/win/win_thread.h"
#include <assert.h>
#include <process.h> // __beginthreadex
#include <Windows.h>
#include <stdexcept>
#include <system_error>
#include <thread>
namespace rocksdb {
namespace port {
struct WindowsThread::Data {
std::function<void()> func_;
uintptr_t handle_;
Data(std::function<void()>&& func) :
func_(std::move(func)),
handle_(0) {
}
Data(const Data&) = delete;
Data& operator=(const Data&) = delete;
static unsigned int __stdcall ThreadProc(void* arg);
};
void WindowsThread::Init(std::function<void()>&& func) {
data_.reset(new Data(std::move(func)));
data_->handle_ = _beginthreadex(NULL,
0, // stack size
&Data::ThreadProc,
data_.get(),
0, // init flag
&th_id_);
if (data_->handle_ == 0) {
throw std::system_error(std::make_error_code(
std::errc::resource_unavailable_try_again),
"Unable to create a thread");
}
}
WindowsThread::WindowsThread() :
data_(nullptr),
th_id_(0)
{}
WindowsThread::~WindowsThread() {
// Must be joined or detached
// before destruction.
// This is the same as std::thread
if (data_) {
if (joinable()) {
assert(false);
std::terminate();
}
data_.reset();
}
}
WindowsThread::WindowsThread(WindowsThread&& o) noexcept :
WindowsThread() {
*this = std::move(o);
}
WindowsThread& WindowsThread::operator=(WindowsThread&& o) noexcept {
if (joinable()) {
assert(false);
std::terminate();
}
data_ = std::move(o.data_);
// Per spec both instances will have the same id
th_id_ = o.th_id_;
return *this;
}
bool WindowsThread::joinable() const {
return (data_ && data_->handle_ != 0);
}
WindowsThread::native_handle_type WindowsThread::native_handle() const {
return reinterpret_cast<native_handle_type>(data_->handle_);
}
unsigned WindowsThread::hardware_concurrency() {
return std::thread::hardware_concurrency();
}
void WindowsThread::join() {
if (!joinable()) {
assert(false);
throw std::system_error(
std::make_error_code(std::errc::invalid_argument),
"Thread is no longer joinable");
}
if (GetThreadId(GetCurrentThread()) == th_id_) {
assert(false);
throw std::system_error(
std::make_error_code(std::errc::resource_deadlock_would_occur),
"Can not join itself");
}
auto ret = WaitForSingleObject(reinterpret_cast<HANDLE>(data_->handle_),
INFINITE);
if (ret != WAIT_OBJECT_0) {
auto lastError = GetLastError();
assert(false);
throw std::system_error(static_cast<int>(lastError),
std::system_category(),
"WaitForSingleObjectFailed");
}
CloseHandle(reinterpret_cast<HANDLE>(data_->handle_));
data_->handle_ = 0;
}
bool WindowsThread::detach() {
if (!joinable()) {
assert(false);
throw std::system_error(
std::make_error_code(std::errc::invalid_argument),
"Thread is no longer available");
}
BOOL ret = CloseHandle(reinterpret_cast<HANDLE>(data_->handle_));
data_->handle_ = 0;
return (ret == TRUE);
}
void WindowsThread::swap(WindowsThread& o) {
data_.swap(o.data_);
std::swap(th_id_, o.th_id_);
}
unsigned int __stdcall WindowsThread::Data::ThreadProc(void* arg) {
auto data = reinterpret_cast<WindowsThread::Data*>(arg);
data->func_();
_endthreadex(0);
return 0;
}
} // namespace port
} // namespace rocksdb
+121
View File
@@ -0,0 +1,121 @@
// Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
// Copyright (c) 2011 The LevelDB Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
#pragma once
#include <memory>
#include <functional>
#include <type_traits>
namespace rocksdb {
namespace port {
// This class is a replacement for std::thread
// 2 reasons we do not like std::thread:
// -- is that it dynamically allocates its internals that are automatically
// freed when the thread terminates and not on the destruction of the
// object. This makes it difficult to control the source of memory
// allocation
// - This implements Pimpl so we can easily replace the guts of the
// object in our private version if necessary.
class WindowsThread {
struct Data;
std::unique_ptr<Data> data_;
unsigned int th_id_;
void Init(std::function<void()>&&);
public:
typedef void* native_handle_type;
// Construct with no thread
WindowsThread();
// Template constructor
//
// This templated constructor accomplishes several things
//
// - Allows the class as whole to be not a template
//
// - take "universal" references to support both _lvalues and _rvalues
//
// - because this constructor is a catchall case in many respects it
// may prevent us from using both the default __ctor, the move __ctor.
// Also it may circumvent copy __ctor deletion. To work around this
// we make sure this one has at least one argument and eliminate
// it from the overload selection when WindowsThread is the first
// argument.
//
// - construct with Fx(Ax...) with a variable number of types/arguments.
//
// - Gathers together the callable object with its arguments and constructs
// a single callable entity
//
// - Makes use of std::function to convert it to a specification-template
// dependent type that both checks the signature conformance to ensure
// that all of the necessary arguments are provided and allows pimpl
// implementation.
template<class Fn,
class... Args,
class = typename std::enable_if<
!std::is_same<typename std::decay<Fn>::type,
WindowsThread>::value>::type>
explicit WindowsThread(Fn&& fx, Args&&... ax) :
WindowsThread() {
// Use binder to create a single callable entity
auto binder = std::bind(std::forward<Fn>(fx),
std::forward<Args>(ax)...);
// Use std::function to take advantage of the type erasure
// so we can still hide implementation within pimpl
// This also makes sure that the binder signature is compliant
std::function<void()> target = binder;
Init(std::move(target));
}
~WindowsThread();
WindowsThread(const WindowsThread&) = delete;
WindowsThread& operator=(const WindowsThread&) = delete;
WindowsThread(WindowsThread&&) noexcept;
WindowsThread& operator=(WindowsThread&&) noexcept;
bool joinable() const;
unsigned int get_id() const { return th_id_; }
native_handle_type native_handle() const;
static unsigned hardware_concurrency();
void join();
bool detach();
void swap(WindowsThread&);
};
} // namespace port
} // namespace rocksdb
namespace std {
inline
void swap(rocksdb::port::WindowsThread& th1,
rocksdb::port::WindowsThread& th2) {
th1.swap(th2);
}
} // namespace std
+2 -3
View File
@@ -74,7 +74,7 @@ LIB_SOURCES = \
table/full_filter_block.cc \
table/get_context.cc \
table/iterator.cc \
table/merger.cc \
table/merging_iterator.cc \
table/meta_blocks.cc \
table/sst_file_writer.cc \
table/plain_table_builder.cc \
@@ -153,7 +153,6 @@ LIB_SOURCES = \
utilities/document/json_document_builder.cc \
utilities/document/json_document.cc \
utilities/env_mirror.cc \
utilities/env_registry.cc \
utilities/geodb/geodb_impl.cc \
utilities/leveldb_options/leveldb_options.cc \
utilities/lua/rocks_lua_compaction_filter.cc \
@@ -299,7 +298,7 @@ MAIN_SOURCES = \
utilities/checkpoint/checkpoint_test.cc \
utilities/document/document_db_test.cc \
utilities/document/json_document_test.cc \
utilities/env_registry_test.cc \
utilities/object_registry_test.cc \
utilities/geodb/geodb_test.cc \
utilities/memory/memory_test.cc \
utilities/merge_operators/string_append/stringappend_test.cc \
+171 -12
View File
@@ -13,6 +13,7 @@
#include <inttypes.h>
#include <stdio.h>
#include <list>
#include <map>
#include <memory>
#include <string>
@@ -53,6 +54,14 @@ extern const std::string kHashIndexPrefixesBlock;
extern const std::string kHashIndexPrefixesMetadataBlock;
typedef BlockBasedTableOptions::IndexType IndexType;
class IndexBuilder;
namespace {
rocksdb::IndexBuilder* CreateIndexBuilder(
IndexType index_type, const InternalKeyComparator* comparator,
const SliceTransform* prefix_extractor, int index_block_restart_interval,
uint64_t index_per_partition);
}
// The interface for building index.
// Instruction for adding a new concrete IndexBuilder:
@@ -101,7 +110,26 @@ class IndexBuilder {
// may therefore perform any operation required for block finalization.
//
// REQUIRES: Finish() has not yet been called.
virtual Status Finish(IndexBlocks* index_blocks) = 0;
inline Status Finish(IndexBlocks* index_blocks) {
// Throw away the changes to last_partition_block_handle. It has no effect
// on the first call to Finish anyway.
BlockHandle last_partition_block_handle;
return Finish(index_blocks, last_partition_block_handle);
}
// This override of Finish can be utilized to build the 2nd level index in
// PartitionIndexBuilder.
//
// index_blocks will be filled with the resulting index data. If the return
// value is Status::InComplete() then it means that the index is partitioned
// and the callee should keep calling Finish until Status::OK() is returned.
// In that case, last_partition_block_handle is pointer to the block written
// with the result of the last call to Finish. This can be utilized to build
// the second level index pointing to each block of partitioned indexes. The
// last call to Finish() that returns Status::OK() populates index_blocks with
// the 2nd level index content.
virtual Status Finish(IndexBlocks* index_blocks,
const BlockHandle& last_partition_block_handle) = 0;
// Get the estimated size for index block.
virtual size_t EstimatedSize() const = 0;
@@ -141,7 +169,9 @@ class ShortenedIndexBuilder : public IndexBuilder {
index_block_builder_.Add(*last_key_in_current_block, handle_encoding);
}
virtual Status Finish(IndexBlocks* index_blocks) override {
virtual Status Finish(
IndexBlocks* index_blocks,
const BlockHandle& last_partition_block_handle) override {
index_blocks->index_block_contents = index_block_builder_.Finish();
return Status::OK();
}
@@ -154,6 +184,108 @@ class ShortenedIndexBuilder : public IndexBuilder {
BlockBuilder index_block_builder_;
};
/**
* IndexBuilder for two-level indexing. Internally it creates a new index for
* each partition and Finish then in order when Finish is called on it
* continiously until Status::OK() is returned.
*
* The format on the disk would be I I I I I I IP where I is block containing a
* partition of indexes built using ShortenedIndexBuilder and IP is a block
* containing a secondary index on the partitions, built using
* ShortenedIndexBuilder.
*/
class PartitionIndexBuilder : public IndexBuilder {
public:
explicit PartitionIndexBuilder(const InternalKeyComparator* comparator,
const SliceTransform* prefix_extractor,
const uint64_t index_per_partition,
int index_block_restart_interval)
: IndexBuilder(comparator),
prefix_extractor_(prefix_extractor),
index_block_builder_(index_block_restart_interval),
index_per_partition_(index_per_partition),
index_block_restart_interval_(index_block_restart_interval) {
sub_index_builder_ =
CreateIndexBuilder(sub_type_, comparator_, prefix_extractor_,
index_block_restart_interval_, index_per_partition_);
}
virtual ~PartitionIndexBuilder() { delete sub_index_builder_; }
virtual void AddIndexEntry(std::string* last_key_in_current_block,
const Slice* first_key_in_next_block,
const BlockHandle& block_handle) override {
sub_index_builder_->AddIndexEntry(last_key_in_current_block,
first_key_in_next_block, block_handle);
num_indexes++;
if (UNLIKELY(first_key_in_next_block == nullptr)) { // no more keys
entries_.push_back({std::string(*last_key_in_current_block),
std::unique_ptr<IndexBuilder>(sub_index_builder_)});
sub_index_builder_ = nullptr;
} else if (num_indexes % index_per_partition_ == 0) {
entries_.push_back({std::string(*last_key_in_current_block),
std::unique_ptr<IndexBuilder>(sub_index_builder_)});
sub_index_builder_ = CreateIndexBuilder(
sub_type_, comparator_, prefix_extractor_,
index_block_restart_interval_, index_per_partition_);
}
}
virtual Status Finish(
IndexBlocks* index_blocks,
const BlockHandle& last_partition_block_handle) override {
assert(!entries_.empty());
// It must be set to null after last key is added
assert(sub_index_builder_ == nullptr);
if (finishing == true) {
Entry& last_entry = entries_.front();
std::string handle_encoding;
last_partition_block_handle.EncodeTo(&handle_encoding);
index_block_builder_.Add(last_entry.key, handle_encoding);
entries_.pop_front();
}
// If there is no sub_index left, then return the 2nd level index.
if (UNLIKELY(entries_.empty())) {
index_blocks->index_block_contents = index_block_builder_.Finish();
return Status::OK();
} else {
// Finish the next partition index in line and Incomplete() to indicate we
// expect more calls to Finish
Entry& entry = entries_.front();
auto s = entry.value->Finish(index_blocks);
finishing = true;
return s.ok() ? Status::Incomplete() : s;
}
}
virtual size_t EstimatedSize() const override {
size_t total = 0;
for (auto it = entries_.begin(); it != entries_.end(); ++it) {
total += it->value->EstimatedSize();
}
total += index_block_builder_.CurrentSizeEstimate();
total +=
sub_index_builder_ == nullptr ? 0 : sub_index_builder_->EstimatedSize();
return total;
}
private:
static const IndexType sub_type_ = BlockBasedTableOptions::kBinarySearch;
struct Entry {
std::string key;
std::unique_ptr<IndexBuilder> value;
};
std::list<Entry> entries_; // list of partitioned indexes and their keys
const SliceTransform* prefix_extractor_;
BlockBuilder index_block_builder_; // top-level index builder
IndexBuilder* sub_index_builder_; // the active partition index builder
uint64_t index_per_partition_;
int index_block_restart_interval_;
uint64_t num_indexes = 0;
bool finishing =
false; // true if Finish is called once but not complete yet.
};
// HashIndexBuilder contains a binary-searchable primary index and the
// metadata for secondary hash index construction.
// The metadata for hash index consists two parts:
@@ -222,9 +354,11 @@ class HashIndexBuilder : public IndexBuilder {
}
}
virtual Status Finish(IndexBlocks* index_blocks) override {
virtual Status Finish(
IndexBlocks* index_blocks,
const BlockHandle& last_partition_block_handle) override {
FlushPendingPrefix();
primary_index_builder_.Finish(index_blocks);
primary_index_builder_.Finish(index_blocks, last_partition_block_handle);
index_blocks->meta_blocks.insert(
{kHashIndexPrefixesBlock.c_str(), prefix_block_});
index_blocks->meta_blocks.insert(
@@ -269,11 +403,12 @@ class HashIndexBuilder : public IndexBuilder {
namespace {
// Create a index builder based on its type.
IndexBuilder* CreateIndexBuilder(IndexType type,
IndexBuilder* CreateIndexBuilder(IndexType index_type,
const InternalKeyComparator* comparator,
const SliceTransform* prefix_extractor,
int index_block_restart_interval) {
switch (type) {
int index_block_restart_interval,
uint64_t index_per_partition) {
switch (index_type) {
case BlockBasedTableOptions::kBinarySearch: {
return new ShortenedIndexBuilder(comparator,
index_block_restart_interval);
@@ -282,6 +417,11 @@ IndexBuilder* CreateIndexBuilder(IndexType type,
return new HashIndexBuilder(comparator, prefix_extractor,
index_block_restart_interval);
}
case BlockBasedTableOptions::kTwoLevelIndexSearch: {
return new PartitionIndexBuilder(comparator, prefix_extractor,
index_per_partition,
index_block_restart_interval);
}
default: {
assert(!"Do not recognize the index type ");
return nullptr;
@@ -512,7 +652,8 @@ struct BlockBasedTableBuilder::Rep {
index_builder(
CreateIndexBuilder(table_options.index_type, &internal_comparator,
&this->internal_prefix_transform,
table_options.index_block_restart_interval)),
table_options.index_block_restart_interval,
table_options.index_per_partition)),
compression_type(_compression_type),
compression_opts(_compression_opts),
compression_dict(_compression_dict),
@@ -852,9 +993,14 @@ Status BlockBasedTableBuilder::Finish() {
}
IndexBuilder::IndexBlocks index_blocks;
auto s = r->index_builder->Finish(&index_blocks);
if (!s.ok()) {
return s;
auto index_builder_status = r->index_builder->Finish(&index_blocks);
if (index_builder_status.IsIncomplete()) {
// We we have more than one index partition then meta_blocks are not
// supported for the index. Currently meta_blocks are used only by
// HashIndexBuilder which is not multi-partition.
assert(index_blocks.meta_blocks.empty());
} else if (!index_builder_status.ok()) {
return index_builder_status;
}
// Write meta blocks and metaindex block with the following order.
@@ -956,8 +1102,21 @@ Status BlockBasedTableBuilder::Finish() {
// flush the meta index block
WriteRawBlock(meta_index_builder.Finish(), kNoCompression,
&metaindex_block_handle);
const bool is_data_block = true;
WriteBlock(index_blocks.index_block_contents, &index_block_handle,
false /* is_data_block */);
!is_data_block);
// If there are more index partitions, finish them and write them out
Status& s = index_builder_status;
while (s.IsIncomplete()) {
s = r->index_builder->Finish(&index_blocks, index_block_handle);
if (!s.ok() && !s.IsIncomplete()) {
return s;
}
WriteBlock(index_blocks.index_block_contents, &index_block_handle,
!is_data_block);
// The last index_block_handle will be for the partition index block
}
}
// Write footer
+144 -44
View File
@@ -153,8 +153,12 @@ class BlockBasedTable::IndexReader {
virtual ~IndexReader() {}
// Create an iterator for index access.
// An iter is passed in, if it is not null, update this one and return it
// If it is null, create a new Iterator
// If iter is null then a new object is created on heap and the callee will
// have the ownership. If a non-null iter is passed in it will be used, and
// the returned value is either the same as iter or a new on-heap object that
// wrapps the passed iter. In the latter case the return value would point to
// a different object then iter and the callee has the ownership of the
// returned object.
virtual InternalIterator* NewIterator(BlockIter* iter = nullptr,
bool total_order_seek = true) = 0;
@@ -175,6 +179,63 @@ class BlockBasedTable::IndexReader {
Statistics* statistics_;
};
// Index that allows binary search lookup in a two-level index structure.
class PartitionIndexReader : public IndexReader {
public:
// Read the partition index from the file and create an instance for
// `PartitionIndexReader`.
// On success, index_reader will be populated; otherwise it will remain
// unmodified.
static Status Create(BlockBasedTable* table, RandomAccessFileReader* file,
const Footer& footer, const BlockHandle& index_handle,
const ImmutableCFOptions& ioptions,
const Comparator* comparator, IndexReader** index_reader,
const PersistentCacheOptions& cache_options) {
std::unique_ptr<Block> index_block;
auto s = ReadBlockFromFile(
file, footer, ReadOptions(), index_handle, &index_block, ioptions,
true /* decompress */, Slice() /*compression dict*/, cache_options,
kDisableGlobalSequenceNumber, 0 /* read_amp_bytes_per_bit */);
if (s.ok()) {
*index_reader = new PartitionIndexReader(
table, comparator, std::move(index_block), ioptions.statistics);
}
return s;
}
// return a two-level iterator: first level is on the partition index
virtual InternalIterator* NewIterator(BlockIter* iter = nullptr,
bool dont_care = true) override {
return NewTwoLevelIterator(
new BlockBasedTable::BlockEntryIteratorState(table_, ReadOptions(),
false),
index_block_->NewIterator(comparator_, iter, true));
}
virtual size_t size() const override { return index_block_->size(); }
virtual size_t usable_size() const override {
return index_block_->usable_size();
}
virtual size_t ApproximateMemoryUsage() const override {
assert(index_block_);
return index_block_->ApproximateMemoryUsage();
}
private:
PartitionIndexReader(BlockBasedTable* table, const Comparator* comparator,
std::unique_ptr<Block>&& index_block, Statistics* stats)
: IndexReader(comparator, stats),
table_(table),
index_block_(std::move(index_block)) {
assert(index_block_ != nullptr);
}
BlockBasedTable* table_;
std::unique_ptr<Block> index_block_;
};
// Index that allows binary search lookup for the first key of each block.
// This class can be viewed as a thin wrapper for `Block` class which already
// supports binary search.
@@ -1352,33 +1413,27 @@ Status BlockBasedTable::MaybeLoadDataBlockToCache(
return s;
}
class BlockBasedTable::BlockEntryIteratorState : public TwoLevelIteratorState {
public:
BlockEntryIteratorState(BlockBasedTable* table,
const ReadOptions& read_options, bool skip_filters)
: TwoLevelIteratorState(table->rep_->ioptions.prefix_extractor !=
nullptr),
table_(table),
read_options_(read_options),
skip_filters_(skip_filters) {}
BlockBasedTable::BlockEntryIteratorState::BlockEntryIteratorState(
BlockBasedTable* table, const ReadOptions& read_options, bool skip_filters)
: TwoLevelIteratorState(table->rep_->ioptions.prefix_extractor != nullptr),
table_(table),
read_options_(read_options),
skip_filters_(skip_filters) {}
InternalIterator* NewSecondaryIterator(const Slice& index_value) override {
return NewDataBlockIterator(table_->rep_, read_options_, index_value);
InternalIterator*
BlockBasedTable::BlockEntryIteratorState::NewSecondaryIterator(
const Slice& index_value) {
// Return a block iterator on the index partition
return NewDataBlockIterator(table_->rep_, read_options_, index_value);
}
bool BlockBasedTable::BlockEntryIteratorState::PrefixMayMatch(
const Slice& internal_key) {
if (read_options_.total_order_seek || skip_filters_) {
return true;
}
bool PrefixMayMatch(const Slice& internal_key) override {
if (read_options_.total_order_seek || skip_filters_) {
return true;
}
return table_->PrefixMayMatch(internal_key);
}
private:
// Don't own table_
BlockBasedTable* table_;
const ReadOptions read_options_;
bool skip_filters_;
};
return table_->PrefixMayMatch(internal_key);
}
// This will be broken if the user specifies an unusual implementation
// of Options.comparator, or if the user specifies an unusual
@@ -1489,13 +1544,30 @@ InternalIterator* BlockBasedTable::NewIterator(const ReadOptions& read_options,
InternalIterator* BlockBasedTable::NewRangeTombstoneIterator(
const ReadOptions& read_options) {
if (rep_->range_del_handle.IsNull()) {
// The block didn't exist, nullptr indicates no range tombstones.
return nullptr;
}
if (rep_->range_del_entry.cache_handle != nullptr) {
// We have a handle to an uncompressed block cache entry that's held for
// this table's lifetime. Increment its refcount before returning an
// iterator based on it since the returned iterator may outlive this table
// reader.
assert(rep_->range_del_entry.value != nullptr);
Cache* block_cache = rep_->table_options.block_cache.get();
assert(block_cache != nullptr);
if (block_cache->Ref(rep_->range_del_entry.cache_handle)) {
auto iter = rep_->range_del_entry.value->NewIterator(
&rep_->internal_comparator, nullptr /* iter */,
true /* total_order_seek */, rep_->ioptions.statistics);
iter->RegisterCleanup(&ReleaseCachedEntry, block_cache,
rep_->range_del_entry.cache_handle);
return iter;
}
}
std::string str;
rep_->range_del_handle.EncodeTo(&str);
// Even though range_del_entry already references the meta-block when block
// cache is enabled, we still call the below function to get another reference
// since the caller may need the iterator beyond this table reader's lifetime.
// The meta-block exists but isn't in uncompressed block cache (maybe because
// it is disabled), so go through the full lookup process.
return NewDataBlockIterator(rep_, read_options, Slice(str));
}
@@ -1534,15 +1606,19 @@ Status BlockBasedTable::Get(const ReadOptions& read_options, const Slice& key,
if (!FullFilterKeyMayMatch(read_options, filter, key)) {
RecordTick(rep_->ioptions.statistics, BLOOM_FILTER_USEFUL);
} else {
BlockIter iiter;
NewIndexIterator(read_options, &iiter);
BlockIter iiter_on_stack;
auto iiter = NewIndexIterator(read_options, &iiter_on_stack);
std::unique_ptr<InternalIterator> iiter_unique_ptr;
if (iiter != &iiter_on_stack) {
iiter_unique_ptr = std::unique_ptr<InternalIterator>(iiter);
}
PinnedIteratorsManager* pinned_iters_mgr = get_context->pinned_iters_mgr();
bool pin_blocks = pinned_iters_mgr && pinned_iters_mgr->PinningEnabled();
bool done = false;
for (iiter.Seek(key); iiter.Valid() && !done; iiter.Next()) {
Slice handle_value = iiter.value();
for (iiter->Seek(key); iiter->Valid() && !done; iiter->Next()) {
Slice handle_value = iiter->value();
BlockHandle handle;
bool not_exist_in_filter =
@@ -1558,7 +1634,7 @@ Status BlockBasedTable::Get(const ReadOptions& read_options, const Slice& key,
break;
} else {
BlockIter biter;
NewDataBlockIterator(rep_, read_options, iiter.value(), &biter);
NewDataBlockIterator(rep_, read_options, iiter->value(), &biter);
if (read_options.read_tier == kBlockCacheTier &&
biter.status().IsIncomplete()) {
@@ -1594,7 +1670,7 @@ Status BlockBasedTable::Get(const ReadOptions& read_options, const Slice& key,
}
}
if (s.ok()) {
s = iiter.status();
s = iiter->status();
}
}
@@ -1615,22 +1691,26 @@ Status BlockBasedTable::Prefetch(const Slice* const begin,
return Status::InvalidArgument(*begin, *end);
}
BlockIter iiter;
NewIndexIterator(ReadOptions(), &iiter);
BlockIter iiter_on_stack;
auto iiter = NewIndexIterator(ReadOptions(), &iiter_on_stack);
std::unique_ptr<InternalIterator> iiter_unique_ptr;
if (iiter != &iiter_on_stack) {
iiter_unique_ptr = std::unique_ptr<InternalIterator>(iiter);
}
if (!iiter.status().ok()) {
if (!iiter->status().ok()) {
// error opening index iterator
return iiter.status();
return iiter->status();
}
// indicates if we are on the last page that need to be pre-fetched
bool prefetching_boundary_page = false;
for (begin ? iiter.Seek(*begin) : iiter.SeekToFirst(); iiter.Valid();
iiter.Next()) {
Slice block_handle = iiter.value();
for (begin ? iiter->Seek(*begin) : iiter->SeekToFirst(); iiter->Valid();
iiter->Next()) {
Slice block_handle = iiter->value();
if (end && comparator.Compare(iiter.key(), *end) >= 0) {
if (end && comparator.Compare(iiter->key(), *end) >= 0) {
if (prefetching_boundary_page) {
break;
}
@@ -1720,6 +1800,11 @@ Status BlockBasedTable::CreateIndexReader(
}
switch (index_type_on_file) {
case BlockBasedTableOptions::kTwoLevelIndexSearch: {
return PartitionIndexReader::Create(
this, file, footer, footer.index_handle(), rep_->ioptions, comparator,
index_reader, rep_->persistent_cache_options);
}
case BlockBasedTableOptions::kBinarySearch: {
return BinarySearchIndexReader::Create(
file, footer, footer.index_handle(), rep_->ioptions, comparator,
@@ -1946,6 +2031,21 @@ Status BlockBasedTable::DumpTable(WritableFile* out_file) {
if (!s.ok()) {
return s;
}
// Output compression dictionary
if (rep_->compression_dict_block != nullptr) {
auto compression_dict = rep_->compression_dict_block->data;
out_file->Append(
"Compression Dictionary:\n"
"--------------------------------------\n");
out_file->Append(" size (bytes): ");
out_file->Append(rocksdb::ToString(compression_dict.size()));
out_file->Append("\n\n");
out_file->Append(" HEX ");
out_file->Append(compression_dict.ToString(true).c_str());
out_file->Append("\n\n");
}
// Output range deletions block
auto* range_del_iter = NewRangeTombstoneIterator(ReadOptions());
if (range_del_iter != nullptr) {
+18 -1
View File
@@ -22,6 +22,7 @@
#include "rocksdb/table.h"
#include "table/table_properties_internal.h"
#include "table/table_reader.h"
#include "table/two_level_iterator.h"
#include "util/cf_options.h"
#include "util/coding.h"
#include "util/file_reader_writer.h"
@@ -149,6 +150,8 @@ class BlockBasedTable : public TableReader {
// The key retrieved are internal keys.
Status GetKVPairsFromDataBlocks(std::vector<KVPairBlock>* kv_pair_blocks);
class BlockEntryIteratorState;
private:
template <class TValue>
struct CachableEntry;
@@ -157,7 +160,6 @@ class BlockBasedTable : public TableReader {
Rep* rep_;
bool compaction_optimized_;
class BlockEntryIteratorState;
// input_iter: if it is not null, update this one and return it as Iterator
static InternalIterator* NewDataBlockIterator(
Rep* rep, const ReadOptions& ro, const Slice& index_value,
@@ -273,4 +275,19 @@ class BlockBasedTable : public TableReader {
void operator=(const TableReader&) = delete;
};
// Maitaning state of a two-level iteration on a partitioned index structure
class BlockBasedTable::BlockEntryIteratorState : public TwoLevelIteratorState {
public:
BlockEntryIteratorState(BlockBasedTable* table,
const ReadOptions& read_options, bool skip_filters);
InternalIterator* NewSecondaryIterator(const Slice& index_value) override;
bool PrefixMayMatch(const Slice& internal_key) override;
private:
// Don't own table_
BlockBasedTable* table_;
const ReadOptions read_options_;
bool skip_filters_;
};
} // namespace rocksdb
+1 -1
View File
@@ -6,7 +6,7 @@
#include <vector>
#include <string>
#include "table/merger.h"
#include "table/merging_iterator.h"
#include "util/testharness.h"
#include "util/testutil.h"
@@ -7,7 +7,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
#include "table/merger.h"
#include "table/merging_iterator.h"
#include <string>
#include <vector>
#include "db/pinned_iterators_manager.h"
File renamed without changes.
+54 -28
View File
@@ -21,6 +21,7 @@
#include "db/memtable.h"
#include "db/write_batch_internal.h"
#include "memtable/stl_wrappers.h"
#include "port/port.h"
#include "rocksdb/cache.h"
#include "rocksdb/db.h"
#include "rocksdb/env.h"
@@ -995,6 +996,7 @@ class TableTest : public testing::Test {
}
return *plain_internal_comparator;
}
void IndexTest(BlockBasedTableOptions table_options);
private:
std::unique_ptr<InternalKeyComparator> plain_internal_comparator;
@@ -1382,13 +1384,18 @@ TEST_F(BlockBasedTableTest, TotalOrderSeekOnHashIndex) {
options.prefix_extractor.reset(NewFixedPrefixTransform(4));
break;
case 3:
default:
// Hash search index with filter policy
table_options.index_type = BlockBasedTableOptions::kHashSearch;
table_options.filter_policy.reset(NewBloomFilterPolicy(10));
options.table_factory.reset(new BlockBasedTableFactory(table_options));
options.prefix_extractor.reset(NewFixedPrefixTransform(4));
break;
case 4:
default:
// Binary search index
table_options.index_type = BlockBasedTableOptions::kTwoLevelIndexSearch;
options.table_factory.reset(new BlockBasedTableFactory(table_options));
break;
}
TableConstructor c(BytewiseComparator(),
@@ -1527,7 +1534,7 @@ void AddInternalKey(TableConstructor* c, const std::string& prefix,
c->Add(k.Encode().ToString(), "v");
}
TEST_F(TableTest, HashIndexTest) {
void TableTest::IndexTest(BlockBasedTableOptions table_options) {
TableConstructor c(BytewiseComparator());
// keys with prefix length 3, make sure the key/value is big enough to fill
@@ -1551,9 +1558,6 @@ TEST_F(TableTest, HashIndexTest) {
stl_wrappers::KVMap kvmap;
Options options;
options.prefix_extractor.reset(NewFixedPrefixTransform(3));
BlockBasedTableOptions table_options;
table_options.index_type = BlockBasedTableOptions::kHashSearch;
table_options.hash_index_allow_collision = true;
table_options.block_size = 1700;
table_options.block_cache = NewLRUCache(1024, 4);
options.table_factory.reset(NewBlockBasedTableFactory(table_options));
@@ -1567,7 +1571,7 @@ TEST_F(TableTest, HashIndexTest) {
auto props = reader->GetTableProperties();
ASSERT_EQ(5u, props->num_data_blocks);
std::unique_ptr<InternalIterator> hash_iter(
std::unique_ptr<InternalIterator> index_iter(
reader->NewIterator(ReadOptions()));
// -- Find keys do not exist, but have common prefix.
@@ -1577,13 +1581,13 @@ TEST_F(TableTest, HashIndexTest) {
// find the lower bound of the prefix
for (size_t i = 0; i < prefixes.size(); ++i) {
hash_iter->Seek(InternalKey(prefixes[i], 0, kTypeValue).Encode());
ASSERT_OK(hash_iter->status());
ASSERT_TRUE(hash_iter->Valid());
index_iter->Seek(InternalKey(prefixes[i], 0, kTypeValue).Encode());
ASSERT_OK(index_iter->status());
ASSERT_TRUE(index_iter->Valid());
// seek the first element in the block
ASSERT_EQ(lower_bound[i], hash_iter->key().ToString());
ASSERT_EQ("v", hash_iter->value().ToString());
ASSERT_EQ(lower_bound[i], index_iter->key().ToString());
ASSERT_EQ("v", index_iter->value().ToString());
}
// find the upper bound of prefixes
@@ -1592,46 +1596,46 @@ TEST_F(TableTest, HashIndexTest) {
// find existing keys
for (const auto& item : kvmap) {
auto ukey = ExtractUserKey(item.first).ToString();
hash_iter->Seek(ukey);
index_iter->Seek(ukey);
// ASSERT_OK(regular_iter->status());
ASSERT_OK(hash_iter->status());
ASSERT_OK(index_iter->status());
// ASSERT_TRUE(regular_iter->Valid());
ASSERT_TRUE(hash_iter->Valid());
ASSERT_TRUE(index_iter->Valid());
ASSERT_EQ(item.first, hash_iter->key().ToString());
ASSERT_EQ(item.second, hash_iter->value().ToString());
ASSERT_EQ(item.first, index_iter->key().ToString());
ASSERT_EQ(item.second, index_iter->value().ToString());
}
for (size_t i = 0; i < prefixes.size(); ++i) {
// the key is greater than any existing keys.
auto key = prefixes[i] + "9";
hash_iter->Seek(InternalKey(key, 0, kTypeValue).Encode());
index_iter->Seek(InternalKey(key, 0, kTypeValue).Encode());
ASSERT_OK(hash_iter->status());
ASSERT_OK(index_iter->status());
if (i == prefixes.size() - 1) {
// last key
ASSERT_TRUE(!hash_iter->Valid());
ASSERT_TRUE(!index_iter->Valid());
} else {
ASSERT_TRUE(hash_iter->Valid());
ASSERT_TRUE(index_iter->Valid());
// seek the first element in the block
ASSERT_EQ(upper_bound[i], hash_iter->key().ToString());
ASSERT_EQ("v", hash_iter->value().ToString());
ASSERT_EQ(upper_bound[i], index_iter->key().ToString());
ASSERT_EQ("v", index_iter->value().ToString());
}
}
// find keys with prefix that don't match any of the existing prefixes.
std::vector<std::string> non_exist_prefixes = {"002", "004", "006", "008"};
for (const auto& prefix : non_exist_prefixes) {
hash_iter->Seek(InternalKey(prefix, 0, kTypeValue).Encode());
index_iter->Seek(InternalKey(prefix, 0, kTypeValue).Encode());
// regular_iter->Seek(prefix);
ASSERT_OK(hash_iter->status());
ASSERT_OK(index_iter->status());
// Seek to non-existing prefixes should yield either invalid, or a
// key with prefix greater than the target.
if (hash_iter->Valid()) {
Slice ukey = ExtractUserKey(hash_iter->key());
if (index_iter->Valid()) {
Slice ukey = ExtractUserKey(index_iter->key());
Slice ukey_prefix = options.prefix_extractor->Transform(ukey);
ASSERT_TRUE(BytewiseComparator()->Compare(prefix, ukey_prefix) < 0);
}
@@ -1639,6 +1643,28 @@ TEST_F(TableTest, HashIndexTest) {
c.ResetTableReader();
}
TEST_F(TableTest, BinaryIndexTest) {
BlockBasedTableOptions table_options;
table_options.index_type = BlockBasedTableOptions::kBinarySearch;
IndexTest(table_options);
}
TEST_F(TableTest, HashIndexTest) {
BlockBasedTableOptions table_options;
table_options.index_type = BlockBasedTableOptions::kHashSearch;
IndexTest(table_options);
}
TEST_F(TableTest, PartitionIndexTest) {
const int max_index_keys = 5;
for (int i = 1; i <= max_index_keys + 1; i++) {
BlockBasedTableOptions table_options;
table_options.index_type = BlockBasedTableOptions::kTwoLevelIndexSearch;
table_options.index_per_partition = i;
IndexTest(table_options);
}
}
// It's very hard to figure out the index block size of a block accurately.
// To make sure we get the index size, we just make sure as key number
// grows, the filter block size also grows.
@@ -2204,8 +2230,8 @@ TEST_F(BlockBasedTableTest, NewIndexIteratorLeak) {
std::unique_ptr<InternalIterator> iter(reader->NewIterator(ro));
};
auto thread1 = std::thread(func1);
auto thread2 = std::thread(func2);
auto thread1 = port::Thread(func1);
auto thread2 = port::Thread(func2);
thread1.join();
thread2.join();
rocksdb::SyncPoint::GetInstance()->DisableProcessing();
+26 -9
View File
@@ -47,7 +47,7 @@
#include "rocksdb/rate_limiter.h"
#include "rocksdb/slice.h"
#include "rocksdb/slice_transform.h"
#include "rocksdb/utilities/env_registry.h"
#include "rocksdb/utilities/object_registry.h"
#include "rocksdb/utilities/optimistic_transaction_db.h"
#include "rocksdb/utilities/options_util.h"
#include "rocksdb/utilities/sim_cache.h"
@@ -72,7 +72,6 @@
#include <io.h> // open/close
#endif
namespace {
using GFLAGS::ParseCommandLineFlags;
using GFLAGS::RegisterFlagValidator;
using GFLAGS::SetUsageMessage;
@@ -459,6 +458,7 @@ DEFINE_bool(verify_checksum, false, "Verify checksum for every block read"
" from storage");
DEFINE_bool(statistics, false, "Database statistics");
DEFINE_string(statistics_string, "", "Serialized statistics string");
static class std::shared_ptr<rocksdb::Statistics> dbstats;
DEFINE_int64(writes, -1, "Number of write operations to do. If negative, do"
@@ -603,7 +603,7 @@ DEFINE_bool(use_stderr_info_logger, false,
DEFINE_bool(use_blob_db, false, "Whether to use BlobDB. ");
enum rocksdb::CompressionType StringToCompressionType(const char* ctype) {
static enum rocksdb::CompressionType StringToCompressionType(const char* ctype) {
assert(ctype);
if (!strcasecmp(ctype, "none"))
@@ -627,7 +627,7 @@ enum rocksdb::CompressionType StringToCompressionType(const char* ctype) {
return rocksdb::kSnappyCompression; // default value
}
std::string ColumnFamilyName(size_t i) {
static std::string ColumnFamilyName(size_t i) {
if (i == 0) {
return rocksdb::kDefaultColumnFamilyName;
} else {
@@ -871,7 +871,7 @@ enum RepFactory {
kCuckoo
};
enum RepFactory StringToRepFactory(const char* ctype) {
static enum RepFactory StringToRepFactory(const char* ctype) {
assert(ctype);
if (!strcasecmp(ctype, "skip_list"))
@@ -939,7 +939,6 @@ static const bool FLAGS_deletepercent_dummy __attribute__((unused)) =
static const bool FLAGS_table_cache_numshardbits_dummy __attribute__((unused)) =
RegisterFlagValidator(&FLAGS_table_cache_numshardbits,
&ValidateTableCacheNumshardbits);
} // namespace
namespace rocksdb {
@@ -1212,7 +1211,7 @@ class ReporterAgent {
abort();
}
reporting_thread_ = std::thread([&]() { SleepAndReport(); });
reporting_thread_ = port::Thread([&]() { SleepAndReport(); });
}
~ReporterAgent() {
@@ -1272,7 +1271,7 @@ class ReporterAgent {
std::atomic<int64_t> total_ops_done_;
int64_t last_report_;
const uint64_t report_interval_secs_;
std::thread reporting_thread_;
rocksdb::port::Thread reporting_thread_;
std::mutex mutex_;
// will notify on stop
std::condition_variable stop_cv_;
@@ -4878,6 +4877,24 @@ int db_bench_tool(int argc, char** argv) {
ParseCommandLineFlags(&argc, &argv, true);
FLAGS_compaction_style_e = (rocksdb::CompactionStyle) FLAGS_compaction_style;
#ifndef ROCKSDB_LITE
if (FLAGS_statistics && !FLAGS_statistics_string.empty()) {
fprintf(stderr,
"Cannot provide both --statistics and --statistics_string.\n");
exit(1);
}
if (!FLAGS_statistics_string.empty()) {
std::unique_ptr<Statistics> custom_stats_guard;
dbstats.reset(NewCustomObject<Statistics>(FLAGS_statistics_string,
&custom_stats_guard));
custom_stats_guard.release();
if (dbstats == nullptr) {
fprintf(stderr, "No Statistics registered matching string: %s\n",
FLAGS_statistics_string.c_str());
exit(1);
}
}
#endif // ROCKSDB_LITE
if (FLAGS_statistics) {
dbstats = rocksdb::CreateDBStatistics();
}
@@ -4903,7 +4920,7 @@ int db_bench_tool(int argc, char** argv) {
fprintf(stderr, "Cannot provide both --hdfs and --env_uri.\n");
exit(1);
} else if (!FLAGS_env_uri.empty()) {
FLAGS_env = NewEnvFromUri(FLAGS_env_uri, &custom_env_guard);
FLAGS_env = NewCustomObject<Env>(FLAGS_env_uri, &custom_env_guard);
if (FLAGS_env == nullptr) {
fprintf(stderr, "No Env registered for URI: %s\n", FLAGS_env_uri.c_str());
exit(1);
+4 -4
View File
@@ -21,7 +21,7 @@
#include "rocksdb/cache.h"
#include "rocksdb/table_properties.h"
#include "rocksdb/utilities/backupable_db.h"
#include "rocksdb/utilities/env_registry.h"
#include "rocksdb/utilities/object_registry.h"
#include "rocksdb/write_batch.h"
#include "rocksdb/write_buffer_manager.h"
#include "table/scoped_arena_iterator.h"
@@ -1770,7 +1770,7 @@ void ChangeCompactionStyleCommand::DoCommand() {
// verify compaction result
files_per_level = "";
int num_files = 0;
for (int i = 0; i < db_->NumberLevels(); i++) {
for (int i = 0; i < db_->NumberLevels(GetCfHandle()); i++) {
db_->GetProperty(GetCfHandle(),
"rocksdb.num-files-at-level" + NumberToString(i),
&property);
@@ -2634,7 +2634,7 @@ void BackupCommand::DoCommand() {
}
printf("open db OK\n");
std::unique_ptr<Env> custom_env_guard;
Env* custom_env = NewEnvFromUri(test_cluster_, &custom_env_guard);
Env* custom_env = NewCustomObject<Env>(test_cluster_, &custom_env_guard);
BackupableDBOptions backup_options =
BackupableDBOptions(test_path_, custom_env);
backup_options.max_background_operations = thread_num_;
@@ -2696,7 +2696,7 @@ void RestoreCommand::Help(std::string& ret) {
void RestoreCommand::DoCommand() {
std::unique_ptr<Env> custom_env_guard;
Env* custom_env = NewEnvFromUri(backup_env_uri_, &custom_env_guard);
Env* custom_env = NewCustomObject<Env>(backup_env_uri_, &custom_env_guard);
std::unique_ptr<BackupEngineReadOnly> restore_engine;
Status status;
{
+4 -4
View File
@@ -29,15 +29,15 @@ void LDBCommandRunner::PrintHelp(const char* exec_name) {
" : Values are input/output as hex\n");
ret.append(" --" + LDBCommand::ARG_HEX +
" : Both keys and values are input/output as hex\n");
ret.append(
" --" + LDBCommand::ARG_CF_NAME +
" : name of the column family to operate on. default: default column "
"family\n");
ret.append("\n");
ret.append(
"The following optional parameters control the database "
"internals:\n");
ret.append(
" --" + LDBCommand::ARG_CF_NAME +
"=<string> : name of the column family to operate on. default: default "
"column family\n");
ret.append(" --" + LDBCommand::ARG_TTL +
" with 'put','get','scan','dump','query','batchput'"
" : DB supports ttl and value is internally timestamp-suffixed\n");
+3 -2
View File
@@ -66,12 +66,13 @@ int main() {
#include <string>
#include <thread>
#include "db/filename.h"
#include "port/port.h"
#include "rocksdb/db.h"
#include "rocksdb/env.h"
#include "rocksdb/options.h"
#include "rocksdb/slice.h"
#include "db/filename.h"
using GFLAGS::ParseCommandLineFlags;
using GFLAGS::RegisterFlagValidator;
@@ -290,7 +291,7 @@ class WriteStress {
// frequently than the first one.
std::atomic<char> key_prefix_[kPrefixSize];
std::atomic<bool> stop_;
std::vector<std::thread> threads_;
std::vector<port::Thread> threads_;
std::unique_ptr<DB> db_;
};
Loaded 100 of 145 files, more files were not shown because too many files have changed in this diff. Show more