Backed out changeset 75acc8e81d81 (bug 1799442) for causing WR tidy bustage. CLOSED TREE

This commit is contained in:
Marian-Vasile Laza 2022-11-18 14:23:58 +02:00
parent e0b9da0442
commit 023eed4276
66 changed files with 1614 additions and 2919 deletions

13
Cargo.lock generated
View File

@ -2240,9 +2240,9 @@ dependencies = [
[[package]]
name = "glean"
version = "51.8.2"
version = "51.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43db04e51b1b7e796177e3bda4fdbeb3b649d6e429524863b1ecf699fabc7d6c"
checksum = "0d1f6f93391e6a54301b0896347a100f5f742ccc89bf48c9bd4dad06e7282716"
dependencies = [
"chrono",
"crossbeam-channel",
@ -2260,9 +2260,9 @@ dependencies = [
[[package]]
name = "glean-core"
version = "51.8.2"
version = "51.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b223c24117a769c9d13e3d9a349187113c364f8ca2831b42651f35d0edba4a5f"
checksum = "8523726fb4d4aa5098198208d5c6e16e26382652a792f42be62caa966bfcd99b"
dependencies = [
"android_logger",
"bincode",
@ -2273,7 +2273,6 @@ dependencies = [
"log",
"once_cell",
"oslog",
"remove_dir_all",
"rkv",
"serde",
"serde_json",
@ -4466,9 +4465,9 @@ dependencies = [
[[package]]
name = "rkv"
version = "0.18.2"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c3b196786090b5b57c9bb0f4afca6ac6a5bfb6182c0161ef32f1ecade43ac47"
checksum = "a6006704273063c72952370ad236b8d58556dcc4f99a95ced4d9ad40f3e80a69"
dependencies = [
"arrayref",
"bincode",

View File

@ -36,7 +36,7 @@ allprojects {
topsrcdir = gradle.mozconfig.topsrcdir
topobjdir = gradle.mozconfig.topobjdir
gleanVersion = "51.8.2"
gleanVersion = "51.8.1"
if (gleanVersion != getRustVersionFor("glean")) {
throw new StopExecutionException("Mismatched Glean version, expected: ${gleanVersion}," +
" found ${getRustVersionFor("glean")}")

65
gfx/wr/Cargo.lock generated
View File

@ -859,9 +859,9 @@ dependencies = [
[[package]]
name = "glean"
version = "51.8.2"
version = "51.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43db04e51b1b7e796177e3bda4fdbeb3b649d6e429524863b1ecf699fabc7d6c"
checksum = "0d1f6f93391e6a54301b0896347a100f5f742ccc89bf48c9bd4dad06e7282716"
dependencies = [
"chrono",
"crossbeam-channel",
@ -879,9 +879,9 @@ dependencies = [
[[package]]
name = "glean-core"
version = "51.8.2"
version = "51.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b223c24117a769c9d13e3d9a349187113c364f8ca2831b42651f35d0edba4a5f"
checksum = "8523726fb4d4aa5098198208d5c6e16e26382652a792f42be62caa966bfcd99b"
dependencies = [
"android_logger",
"bincode",
@ -892,7 +892,6 @@ dependencies = [
"log",
"once_cell",
"oslog",
"remove_dir_all",
"rkv",
"serde",
"serde_json",
@ -1534,9 +1533,9 @@ checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e"
[[package]]
name = "ordered-float"
version = "3.4.0"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d84eb1409416d254e4a9c8fa56cc24701755025b458f0fcd8e59e1f5f40c23bf"
checksum = "18869315e81473c951eb56ad5558bbc56978562d3ecfb87abb7a1e944cea4518"
dependencies = [
"num-traits",
]
@ -1597,12 +1596,31 @@ dependencies = [
"winapi",
]
[[package]]
name = "paste"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880"
dependencies = [
"paste-impl",
"proc-macro-hack",
]
[[package]]
name = "paste"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc"
[[package]]
name = "paste-impl"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6"
dependencies = [
"proc-macro-hack",
]
[[package]]
name = "peek-poke"
version = "0.3.0"
@ -1697,6 +1715,12 @@ dependencies = [
"version_check",
]
[[package]]
name = "proc-macro-hack"
version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro2"
version = "1.0.36"
@ -1819,20 +1843,11 @@ version = "0.6.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae"
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
]
[[package]]
name = "rkv"
version = "0.18.2"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c3b196786090b5b57c9bb0f4afca6ac6a5bfb6182c0161ef32f1ecade43ac47"
checksum = "28e2e15d3fff125cfc4fb3f1b226ff83af057c4715061ded16193b7142beefc9"
dependencies = [
"arrayref",
"bincode",
@ -1843,7 +1858,7 @@ dependencies = [
"lmdb-rkv",
"log",
"ordered-float",
"paste",
"paste 0.1.18",
"serde",
"serde_derive",
"thiserror",
@ -1920,9 +1935,9 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.147"
version = "1.0.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
dependencies = [
"serde_derive",
]
@ -1938,9 +1953,9 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.147"
version = "1.0.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
dependencies = [
"proc-macro2",
"quote",
@ -2210,7 +2225,7 @@ dependencies = [
"cargo_metadata",
"log",
"once_cell",
"paste",
"paste 1.0.7",
"static_assertions",
"uniffi_macros",
]
@ -2230,7 +2245,7 @@ dependencies = [
"goblin",
"heck",
"once_cell",
"paste",
"paste 1.0.7",
"serde",
"serde_json",
"toml",

View File

@ -51,7 +51,7 @@ svg_fmt = "0.4"
tracy-rs = "0.1.2"
derive_more = { version = "0.99", default-features = false, features = ["add_assign"] }
etagere = "0.2.6"
glean = "51.8.2"
glean = "51.8.1"
fog = { version = "0.1.0", optional = true }
swgl = { path = "../swgl", optional = true }
topological-sort = "0.1"

View File

@ -135,7 +135,7 @@ pth:xpcom/geckoprocesstypes_generator
pth:xpcom/idl-parser
# glean-sdk may not be installable if a wheel isn't available
# and it has to be built from source.
pypi-optional:glean-sdk==51.8.2:telemetry will not be collected
pypi-optional:glean-sdk==51.8.1:telemetry will not be collected
# Mach gracefully handles the case where `psutil` is unavailable.
# We aren't (yet) able to pin packages in automation, so we have to
# support down to the oldest locally-installed version (5.4.2).

View File

@ -12,7 +12,7 @@ log = "0.4"
moz_task = { path = "../../../../xpcom/rust/moz_task" }
nserror = { path = "../../../../xpcom/rust/nserror" }
nsstring = { path = "../../../../xpcom/rust/nsstring" }
rkv = { version = "0.18", default-features = false }
rkv = { version = "0.17", default-features = false }
rust_cascade = "1.4.0"
sha2 = "0.10.2"
storage_variant = { path = "../../../../storage/variant" }

View File

@ -550,12 +550,6 @@ criteria = "safe-to-deploy"
version = "51.8.1"
notes = "Maintained by the Glean Team at Mozilla"
[[audits.glean]]
who = "Chris H-C <chutten@mozilla.com>"
criteria = "safe-to-deploy"
version = "51.8.2"
notes = "Maintained by the Glean Team at Mozilla."
[[audits.glean]]
who = "Jan-Erik Rediger <jrediger@mozilla.com>"
criteria = "safe-to-deploy"
@ -621,12 +615,6 @@ criteria = "safe-to-deploy"
version = "51.8.1"
notes = "Maintained by the Glean Team at Mozilla"
[[audits.glean-core]]
who = "Chris H-C <chutten@mozilla.com>"
criteria = "safe-to-deploy"
version = "51.8.2"
notes = "Maintained by the Glean Team at Mozilla."
[[audits.glean-core]]
who = "Jan-Erik Rediger <jrediger@mozilla.com>"
criteria = "safe-to-deploy"
@ -1069,12 +1057,6 @@ who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
delta = "0.6.26 -> 0.6.27"
[[audits.rkv]]
who = "Chris H-C <chutten@mozilla.com>"
criteria = "safe-to-deploy"
version = "0.18.2"
notes = "Maintained by Jan-Erik and :krosylight."
[[audits.ron]]
who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"

View File

@ -1091,6 +1091,10 @@ criteria = "safe-to-deploy"
version = "0.2.8"
criteria = "safe-to-deploy"
[[exemptions.rkv]]
version = "0.17.1"
criteria = "safe-to-deploy"
[[exemptions.ron]]
version = "0.7.0"
criteria = "safe-to-deploy"

File diff suppressed because one or more lines are too long

View File

@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "glean-core"
version = "51.8.2"
version = "51.8.1"
authors = [
"Jan-Erik Rediger <jrediger@mozilla.com>",
"The Glean Team <glean-team@mozilla.com>",
@ -55,12 +55,8 @@ version = "0.4.8"
[dependencies.once_cell]
version = "1.4.1"
[dependencies.remove_dir_all]
version = "0.5.3"
[dependencies.rkv]
version = "0.18.2"
features = ["lmdb"]
version = "0.17.0"
default-features = false
[dependencies.serde]

View File

@ -300,7 +300,7 @@ impl EventDatabase {
// safe unwrap, only error case is poisoning
let _lock = self.file_lock.write().unwrap();
remove_dir_all::remove_dir_all(&self.path)?;
std::fs::remove_dir_all(&self.path)?;
create_dir_all(&self.path)?;
Ok(())

View File

@ -355,7 +355,7 @@ impl PingMaker {
pub fn clear_pending_pings(&self, data_path: &Path) -> Result<()> {
let pings_dir = self.get_pings_dir(data_path, None)?;
remove_dir_all::remove_dir_all(&pings_dir)?;
std::fs::remove_dir_all(&pings_dir)?;
create_dir_all(&pings_dir)?;
log::debug!("All pending pings deleted");

View File

@ -1 +1 @@
{"files":{"Cargo.toml":"82a921c6455e7365042a426efc5a8d34996c7ced9c71db962327606a6f39c9fb","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"5bc5b1c46695f628e1023662752272e938a963b535d5686bd1ecc433f9e018c4","src/common_test.rs":"68f6d408cb7b683fa32c8b38a4df1e6c45bfd77c0c90ca35976ea7548bbc4b2f","src/configuration.rs":"37ad5b3e7d4e31dd04a7d6690179168b5f2768d87dd36056dee5d08bdbe20fb2","src/core_metrics.rs":"76ac5350cb6f82d9a193d519b085a08f138dceba77da3514bd0c636bcdefefca","src/lib.rs":"7caacc2b5f389bf5d3829a74e77c100b457a63ddf3a914225f26556e3b8bfb18","src/net/http_uploader.rs":"43812a70d19a38e8d7a093c8076c2b6345372c3c861b0f3511428762700a65e0","src/net/mod.rs":"e05e61860f5828caa529c3ea75a2fff7371bfa3dce057077a74c09baf41a568a","src/private/event.rs":"02bbebf545695812e5055741cc0b5f3c99eda2039e684e26fcdd5f087ed15fe3","src/private/mod.rs":"0364ecf5f0439443a5b209583f4ff2c474b79f7c253c981ab0b7cdc528368698","src/private/ping.rs":"cbdc57f41fc9d46e56b4dfff91ac683753d1f8b3ecd0aa9bc3419e3595b8b81b","src/system.rs":"4e0ec743f6d06a9c83e46c95d0286d5745f4642398c942fce8ae7a1ea5202d37","src/test.rs":"1d9a01fa6befdc04e97caeb58ccebd67c840965ff0417b6b2ba9e53aa108a069","tests/common/mod.rs":"37cd4c48e140c793b852ae09fb3e812da28a4412977295015bcbffd632fcf294","tests/init_fails.rs":"9b78226a4e3220de5b64a205a97b8d5778d1700391b5b71c7819b6cdd120747e","tests/never_init.rs":"1f33b8ce7ca3514b57b48cc16d98408974c85cf8aa7d13257ffc2ad878ebb295","tests/no_time_to_init.rs":"494dcddce49f279c6508f484ee59cf8bb83e7324de07bdbc1142f2a066b7f6a1","tests/overflowing_preinit.rs":"396206d5078b7e6c148bbf2aecb0f963cfaa4d7eff3fc7bf6590125076ee6113","tests/persist_ping_lifetime.rs":"2297d4b208e14188e6dcca2d4806b805cfc7dd824d21bd143a7803b95e0709f4","tests/persist_ping_lifetime_nopanic.rs":"06f1f3ca3b8a6c8b7fc4d6fc48d0e1d2ccffd32139f080db0a95003e9edd507d","tests/schema.rs":"a96089f828928b6be1fad7815e3269f5693af1b773e570312b357a29af28122a","tests/simple.rs":"a1d72af899293390bb955ca379baafb89c29bb746630409f8c51f453d222dbad"},"package":"43db04e51b1b7e796177e3bda4fdbeb3b649d6e429524863b1ecf699fabc7d6c"}
{"files":{"Cargo.toml":"09467d10e79fb01d0e70b45095b16c3c064501920b9f0892cf4903ba405cb2da","LICENSE":"1f256ecad192880510e84ad60474eab7589218784b9a50bc7ceee34c2b91f1d5","README.md":"5bc5b1c46695f628e1023662752272e938a963b535d5686bd1ecc433f9e018c4","src/common_test.rs":"68f6d408cb7b683fa32c8b38a4df1e6c45bfd77c0c90ca35976ea7548bbc4b2f","src/configuration.rs":"37ad5b3e7d4e31dd04a7d6690179168b5f2768d87dd36056dee5d08bdbe20fb2","src/core_metrics.rs":"76ac5350cb6f82d9a193d519b085a08f138dceba77da3514bd0c636bcdefefca","src/lib.rs":"7caacc2b5f389bf5d3829a74e77c100b457a63ddf3a914225f26556e3b8bfb18","src/net/http_uploader.rs":"43812a70d19a38e8d7a093c8076c2b6345372c3c861b0f3511428762700a65e0","src/net/mod.rs":"e05e61860f5828caa529c3ea75a2fff7371bfa3dce057077a74c09baf41a568a","src/private/event.rs":"02bbebf545695812e5055741cc0b5f3c99eda2039e684e26fcdd5f087ed15fe3","src/private/mod.rs":"0364ecf5f0439443a5b209583f4ff2c474b79f7c253c981ab0b7cdc528368698","src/private/ping.rs":"cbdc57f41fc9d46e56b4dfff91ac683753d1f8b3ecd0aa9bc3419e3595b8b81b","src/system.rs":"4e0ec743f6d06a9c83e46c95d0286d5745f4642398c942fce8ae7a1ea5202d37","src/test.rs":"1d9a01fa6befdc04e97caeb58ccebd67c840965ff0417b6b2ba9e53aa108a069","tests/common/mod.rs":"37cd4c48e140c793b852ae09fb3e812da28a4412977295015bcbffd632fcf294","tests/init_fails.rs":"9b78226a4e3220de5b64a205a97b8d5778d1700391b5b71c7819b6cdd120747e","tests/never_init.rs":"1f33b8ce7ca3514b57b48cc16d98408974c85cf8aa7d13257ffc2ad878ebb295","tests/no_time_to_init.rs":"494dcddce49f279c6508f484ee59cf8bb83e7324de07bdbc1142f2a066b7f6a1","tests/overflowing_preinit.rs":"396206d5078b7e6c148bbf2aecb0f963cfaa4d7eff3fc7bf6590125076ee6113","tests/persist_ping_lifetime.rs":"2297d4b208e14188e6dcca2d4806b805cfc7dd824d21bd143a7803b95e0709f4","tests/persist_ping_lifetime_nopanic.rs":"06f1f3ca3b8a6c8b7fc4d6fc48d0e1d2ccffd32139f080db0a95003e9edd507d","tests/schema.rs":"a96089f828928b6be1fad7815e3269f5693af1b773e570312b357a29af28122a","tests/simple.rs":"a1d72af899293390bb955ca379baafb89c29bb746630409f8c51f453d222dbad"},"package":"0d1f6f93391e6a54301b0896347a100f5f742ccc89bf48c9bd4dad06e7282716"}

View File

@ -12,7 +12,7 @@
[package]
edition = "2018"
name = "glean"
version = "51.8.2"
version = "51.8.1"
authors = [
"Jan-Erik Rediger <jrediger@mozilla.com>",
"The Glean Team <glean-team@mozilla.com>",
@ -41,7 +41,7 @@ features = ["serde"]
version = "0.5"
[dependencies.glean-core]
version = "51.8.2"
version = "51.8.1"
[dependencies.inherent]
version = "1"

File diff suppressed because one or more lines are too long

91
third_party/rust/rkv/Cargo.lock generated vendored
View File

@ -37,9 +37,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "cc"
version = "1.0.76"
version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f"
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "cfg-if"
@ -49,19 +49,20 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "fastrand"
version = "1.8.0"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
dependencies = [
"instant",
]
[[package]]
name = "form_urlencoded"
version = "1.1.0"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
dependencies = [
"matches",
"percent-encoding",
]
@ -73,10 +74,11 @@ checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005"
[[package]]
name = "idna"
version = "0.3.0"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
dependencies = [
"matches",
"unicode-bidi",
"unicode-normalization",
]
@ -98,9 +100,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.137"
version = "0.2.126"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
[[package]]
name = "lmdb-rkv"
@ -134,6 +136,12 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "matches"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]]
name = "num-traits"
version = "0.2.15"
@ -145,54 +153,54 @@ dependencies = [
[[package]]
name = "ordered-float"
version = "3.4.0"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d84eb1409416d254e4a9c8fa56cc24701755025b458f0fcd8e59e1f5f40c23bf"
checksum = "96bcbab4bfea7a59c2c0fe47211a1ac4e3e96bea6eb446d704f310bc5c732ae2"
dependencies = [
"num-traits",
]
[[package]]
name = "paste"
version = "1.0.9"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1"
checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc"
[[package]]
name = "percent-encoding"
version = "2.2.0"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "pkg-config"
version = "0.3.26"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]]
name = "proc-macro2"
version = "1.0.47"
version = "1.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
dependencies = [
"bitflags",
]
@ -208,7 +216,7 @@ dependencies = [
[[package]]
name = "rkv"
version = "0.18.2"
version = "0.17.1"
dependencies = [
"arrayref",
"bincode",
@ -230,18 +238,18 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.147"
version = "1.0.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.147"
version = "1.0.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
dependencies = [
"proc-macro2",
"quote",
@ -250,9 +258,9 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.103"
version = "1.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf"
dependencies = [
"proc-macro2",
"quote",
@ -275,18 +283,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.37"
version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.37"
version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
dependencies = [
"proc-macro2",
"quote",
@ -316,27 +324,28 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
[[package]]
name = "unicode-ident"
version = "1.0.5"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee"
[[package]]
name = "unicode-normalization"
version = "0.1.22"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9"
dependencies = [
"tinyvec",
]
[[package]]
name = "url"
version = "2.3.1"
version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
dependencies = [
"form_urlencoded",
"idna",
"matches",
"percent-encoding",
]

View File

@ -11,9 +11,8 @@
[package]
edition = "2018"
rust-version = "1.58"
name = "rkv"
version = "0.18.2"
version = "0.17.1"
authors = [
"Richard Newman <rnewman@twinql.com>",
"Nan Jiang <najiang@mozilla.com>",
@ -34,28 +33,6 @@ categories = ["database"]
license = "Apache-2.0"
repository = "https://github.com/mozilla/rkv"
[[bin]]
name = "rand"
path = "src/bin/rand.rs"
required-features = ["lmdb"]
[[bin]]
name = "dump"
path = "src/bin/dump.rs"
required-features = ["lmdb"]
[[test]]
name = "env-all"
required-features = ["lmdb"]
[[test]]
name = "env-lmdb"
required-features = ["lmdb"]
[[test]]
name = "env-migration"
required-features = ["lmdb"]
[dependencies.arrayref]
version = "0.3"
@ -63,7 +40,7 @@ version = "0.3"
version = "1.0"
[dependencies.bitflags]
version = "1.2"
version = "1.1"
[dependencies.byteorder]
version = "1"
@ -76,7 +53,6 @@ version = "1.1"
[dependencies.lmdb-rkv]
version = "0.14"
optional = true
[dependencies.log]
version = "0.4.4"
@ -88,7 +64,7 @@ version = "3.0.0"
version = "1.0.6"
[dependencies.serde]
version = "1.0.144"
version = "1.0"
features = [
"derive",
"rc",
@ -119,17 +95,7 @@ default = [
"db-dup-sort",
"db-int-key",
]
lmdb = ["lmdb-rkv"]
no-canonicalize-path = []
with-asan = [
"lmdb",
"lmdb-rkv/with-asan",
]
with-fuzzer = [
"lmdb",
"lmdb-rkv/with-fuzzer",
]
with-fuzzer-no-link = [
"lmdb",
"lmdb-rkv/with-fuzzer-no-link",
]
with-asan = ["lmdb-rkv/with-asan"]
with-fuzzer = ["lmdb-rkv/with-fuzzer"]
with-fuzzer-no-link = ["lmdb-rkv/with-fuzzer-no-link"]

View File

@ -1,6 +1,7 @@
# rkv
[![CI Build Status](https://github.com/mozilla/rkv/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/mozilla/rkv/actions/workflows/ci.yml)
[![Travis CI Build Status](https://travis-ci.org/mozilla/rkv.svg?branch=master)](https://travis-ci.org/mozilla/rkv)
[![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/lk936u5y5bi6qafb/branch/master?svg=true)](https://ci.appveyor.com/project/mykmelez/rkv/branch/master)
[![Documentation](https://docs.rs/rkv/badge.svg)](https://docs.rs/rkv/)
[![Crate](https://img.shields.io/crates/v/rkv.svg)](https://crates.io/crates/rkv)

View File

@ -7,13 +7,25 @@
//!
//! cargo run --example iterator
use std::{fs, str};
use std::{
fs,
str,
};
use tempfile::Builder;
use rkv::{
backend::{SafeMode, SafeModeDatabase, SafeModeEnvironment},
Manager, Rkv, SingleStore, StoreError, StoreOptions, Value,
backend::{
Lmdb,
LmdbDatabase,
LmdbEnvironment,
},
Manager,
Rkv,
SingleStore,
StoreError,
StoreOptions,
Value,
};
fn main() {
@ -21,8 +33,8 @@ fn main() {
fs::create_dir_all(root.path()).unwrap();
let p = root.path();
let mut manager = Manager::<SafeModeEnvironment>::singleton().write().unwrap();
let created_arc = manager.get_or_create(p, Rkv::new::<SafeMode>).unwrap();
let mut manager = Manager::<LmdbEnvironment>::singleton().write().unwrap();
let created_arc = manager.get_or_create(p, Rkv::new::<Lmdb>).unwrap();
let k = created_arc.read().unwrap();
let store = k.open_single("store", StoreOptions::create()).unwrap();
@ -35,8 +47,7 @@ fn main() {
// returns the (key, value) tuples in order.
let mut iter = store.iter_start(&reader).unwrap();
while let Some(Ok((country, city))) = iter.next() {
let country = str::from_utf8(country).unwrap();
println!("{country}, {city:?}");
println!("{}, {:?}", str::from_utf8(country).unwrap(), city);
}
println!();
@ -45,21 +56,18 @@ fn main() {
// than the given key.
let mut iter = store.iter_from(&reader, "Japan").unwrap();
while let Some(Ok((country, city))) = iter.next() {
println!("{}, {city:?}", str::from_utf8(country).unwrap());
println!("{}, {:?}", str::from_utf8(country).unwrap(), city);
}
println!();
println!("Iterating from the given prefix...");
let mut iter = store.iter_from(&reader, "Un").unwrap();
while let Some(Ok((country, city))) = iter.next() {
println!("{}, {city:?}", str::from_utf8(country).unwrap());
println!("{}, {:?}", str::from_utf8(country).unwrap(), city);
}
}
fn populate_store(
k: &Rkv<SafeModeEnvironment>,
store: SingleStore<SafeModeDatabase>,
) -> Result<(), StoreError> {
fn populate_store(k: &Rkv<LmdbEnvironment>, store: SingleStore<LmdbDatabase>) -> Result<(), StoreError> {
let mut writer = k.write()?;
for (country, city) in vec![
("Canada", Value::Str("Ottawa")),

View File

@ -12,12 +12,21 @@ use std::fs;
use tempfile::Builder;
use rkv::{
backend::{SafeMode, SafeModeDatabase, SafeModeEnvironment, SafeModeRwTransaction},
Manager, Rkv, StoreOptions, Value,
backend::{
BackendStat,
Lmdb,
LmdbDatabase,
LmdbEnvironment,
LmdbRwTransaction,
},
Manager,
Rkv,
StoreOptions,
Value,
};
type MultiStore = rkv::MultiStore<SafeModeDatabase>;
type Writer<'w> = rkv::Writer<SafeModeRwTransaction<'w>>;
type MultiStore = rkv::MultiStore<LmdbDatabase>;
type Writer<'w> = rkv::Writer<LmdbRwTransaction<'w>>;
fn getput<'w, 's>(store: MultiStore, writer: &'w mut Writer, ids: &'s mut Vec<String>) {
let keys = vec!["str1", "str2", "str3"];
@ -43,9 +52,7 @@ fn delete(store: MultiStore, writer: &mut Writer) {
let vals = vec!["string uno", "string quatro", "string siete"];
// we convert the writer into a cursor so that we can safely read
for i in 0..keys.len() {
store
.delete(writer, &keys[i], &Value::Str(vals[i]))
.unwrap();
store.delete(writer, &keys[i], &Value::Str(vals[i])).unwrap();
}
}
@ -55,8 +62,8 @@ fn main() {
let p = root.path();
// The manager enforces that each process opens the same lmdb environment at most once
let mut manager = Manager::<SafeModeEnvironment>::singleton().write().unwrap();
let created_arc = manager.get_or_create(p, Rkv::new::<SafeMode>).unwrap();
let mut manager = Manager::<LmdbEnvironment>::singleton().write().unwrap();
let created_arc = manager.get_or_create(p, Rkv::new::<Lmdb>).unwrap();
let k = created_arc.read().unwrap();
// Creates a store called "store"
@ -68,31 +75,13 @@ fn main() {
// Use a writer to mutate the store
let mut writer = k.write().unwrap();
store.put(&mut writer, "int", &Value::I64(1234)).unwrap();
store
.put(&mut writer, "uint", &Value::U64(1234_u64))
.unwrap();
store
.put(&mut writer, "float", &Value::F64(1234.0.into()))
.unwrap();
store
.put(&mut writer, "instant", &Value::Instant(1_528_318_073_700))
.unwrap();
store
.put(&mut writer, "boolean", &Value::Bool(true))
.unwrap();
store
.put(&mut writer, "string", &Value::Str("héllo, yöu"))
.unwrap();
store
.put(
&mut writer,
"json",
&Value::Json(r#"{"foo":"bar", "number": 1}"#),
)
.unwrap();
store
.put(&mut writer, "blob", &Value::Blob(b"blob"))
.unwrap();
store.put(&mut writer, "uint", &Value::U64(1234_u64)).unwrap();
store.put(&mut writer, "float", &Value::F64(1234.0.into())).unwrap();
store.put(&mut writer, "instant", &Value::Instant(1_528_318_073_700)).unwrap();
store.put(&mut writer, "boolean", &Value::Bool(true)).unwrap();
store.put(&mut writer, "string", &Value::Str("héllo, yöu")).unwrap();
store.put(&mut writer, "json", &Value::Json(r#"{"foo":"bar", "number": 1}"#)).unwrap();
store.put(&mut writer, "blob", &Value::Blob(b"blob")).unwrap();
writer.commit().unwrap();
}
@ -100,33 +89,15 @@ fn main() {
{
let mut ids = Vec::new();
let mut writer = k.write().unwrap();
multistore
.put(&mut writer, "str1", &Value::Str("string uno"))
.unwrap();
multistore
.put(&mut writer, "str1", &Value::Str("string dos"))
.unwrap();
multistore
.put(&mut writer, "str1", &Value::Str("string tres"))
.unwrap();
multistore
.put(&mut writer, "str2", &Value::Str("string quatro"))
.unwrap();
multistore
.put(&mut writer, "str2", &Value::Str("string cinco"))
.unwrap();
multistore
.put(&mut writer, "str2", &Value::Str("string seis"))
.unwrap();
multistore
.put(&mut writer, "str3", &Value::Str("string siete"))
.unwrap();
multistore
.put(&mut writer, "str3", &Value::Str("string ocho"))
.unwrap();
multistore
.put(&mut writer, "str3", &Value::Str("string nueve"))
.unwrap();
multistore.put(&mut writer, "str1", &Value::Str("string uno")).unwrap();
multistore.put(&mut writer, "str1", &Value::Str("string dos")).unwrap();
multistore.put(&mut writer, "str1", &Value::Str("string tres")).unwrap();
multistore.put(&mut writer, "str2", &Value::Str("string quatro")).unwrap();
multistore.put(&mut writer, "str2", &Value::Str("string cinco")).unwrap();
multistore.put(&mut writer, "str2", &Value::Str("string seis")).unwrap();
multistore.put(&mut writer, "str3", &Value::Str("string siete")).unwrap();
multistore.put(&mut writer, "str3", &Value::Str("string ocho")).unwrap();
multistore.put(&mut writer, "str3", &Value::Str("string nueve")).unwrap();
getput(multistore, &mut writer, &mut ids);
writer.commit().unwrap();
let mut writer = k.write().unwrap();
@ -146,10 +117,7 @@ fn main() {
println!("Get string {:?}", store.get(&reader, "string").unwrap());
println!("Get json {:?}", store.get(&reader, "json").unwrap());
println!("Get blob {:?}", store.get(&reader, "blob").unwrap());
println!(
"Get non-existent {:?}",
store.get(&reader, "non-existent").unwrap()
);
println!("Get non-existent {:?}", store.get(&reader, "non-existent").unwrap());
}
println!("Looking up keys via Writer.get()...");
@ -158,17 +126,11 @@ fn main() {
store.put(&mut writer, "foo", &Value::Str("bar")).unwrap();
store.put(&mut writer, "bar", &Value::Str("baz")).unwrap();
store.delete(&mut writer, "foo").unwrap();
println!(
"It should be None! ({:?})",
store.get(&writer, "foo").unwrap()
);
println!("It should be None! ({:?})", store.get(&writer, "foo").unwrap());
println!("Get bar ({:?})", store.get(&writer, "bar").unwrap());
writer.commit().unwrap();
let reader = k.read().expect("reader");
println!(
"It should be None! ({:?})",
store.get(&reader, "foo").unwrap()
);
println!("It should be None! ({:?})", store.get(&reader, "foo").unwrap());
println!("Get bar {:?}", store.get(&reader, "bar").unwrap());
}
@ -180,10 +142,7 @@ fn main() {
writer.abort();
let reader = k.read().expect("reader");
println!(
"It should be None! ({:?})",
store.get(&reader, "foo").unwrap()
);
println!("It should be None! ({:?})", store.get(&reader, "foo").unwrap());
// Explicitly aborting a transaction is not required unless an early
// abort is desired, since both read and write transactions will
// implicitly be aborted once they go out of scope.
@ -195,10 +154,7 @@ fn main() {
let mut writer = k.write().unwrap();
store.put(&mut writer, "foo", &Value::Str("bar")).unwrap();
store.delete(&mut writer, "foo").unwrap();
println!(
"It should be None! ({:?})",
store.get(&writer, "foo").unwrap()
);
println!("It should be None! ({:?})", store.get(&writer, "foo").unwrap());
writer.commit().unwrap();
// Committing a transaction consumes the writer, preventing you
@ -217,36 +173,22 @@ fn main() {
writer.commit().unwrap();
let reader = k.read().expect("reader");
println!(
"It should be None! ({:?})",
store.get(&reader, "foo").unwrap()
);
println!(
"It should be None! ({:?})",
store.get(&reader, "bar").unwrap()
);
println!("It should be None! ({:?})", store.get(&reader, "foo").unwrap());
println!("It should be None! ({:?})", store.get(&reader, "bar").unwrap());
}
println!("Write and read on multiple stores...");
{
let another_store = k
.open_single("another_store", StoreOptions::create())
.unwrap();
let another_store = k.open_single("another_store", StoreOptions::create()).unwrap();
let mut writer = k.write().unwrap();
store.put(&mut writer, "foo", &Value::Str("bar")).unwrap();
another_store
.put(&mut writer, "foo", &Value::Str("baz"))
.unwrap();
another_store.put(&mut writer, "foo", &Value::Str("baz")).unwrap();
writer.commit().unwrap();
let reader = k.read().unwrap();
println!(
"Get from store value: {:?}",
store.get(&reader, "foo").unwrap()
);
println!(
"Get from another store value: {:?}",
another_store.get(&reader, "foo").unwrap()
);
println!("Get from store value: {:?}", store.get(&reader, "foo").unwrap());
println!("Get from another store value: {:?}", another_store.get(&reader, "foo").unwrap());
}
println!("Environment statistics: btree depth = {}", k.stat().unwrap().depth());
}

View File

@ -9,7 +9,6 @@
// specific language governing permissions and limitations under the License.
mod common;
#[cfg(feature = "lmdb")]
mod impl_lmdb;
mod impl_safe;
mod traits;
@ -17,24 +16,39 @@ mod traits;
pub use common::*;
pub use traits::*;
#[cfg(feature = "lmdb")]
pub use impl_lmdb::{
ArchMigrateError as LmdbArchMigrateError, ArchMigrateResult as LmdbArchMigrateResult,
ArchMigrator as LmdbArchMigrator, DatabaseFlagsImpl as LmdbDatabaseFlags,
DatabaseImpl as LmdbDatabase, EnvironmentBuilderImpl as Lmdb,
EnvironmentFlagsImpl as LmdbEnvironmentFlags, EnvironmentImpl as LmdbEnvironment,
ErrorImpl as LmdbError, InfoImpl as LmdbInfo, IterImpl as LmdbIter,
RoCursorImpl as LmdbRoCursor, RoTransactionImpl as LmdbRoTransaction,
RwCursorImpl as LmdbRwCursor, RwTransactionImpl as LmdbRwTransaction, StatImpl as LmdbStat,
ArchMigrateError as LmdbArchMigrateError,
ArchMigrateResult as LmdbArchMigrateResult,
ArchMigrator as LmdbArchMigrator,
DatabaseFlagsImpl as LmdbDatabaseFlags,
DatabaseImpl as LmdbDatabase,
EnvironmentBuilderImpl as Lmdb,
EnvironmentFlagsImpl as LmdbEnvironmentFlags,
EnvironmentImpl as LmdbEnvironment,
ErrorImpl as LmdbError,
InfoImpl as LmdbInfo,
IterImpl as LmdbIter,
RoCursorImpl as LmdbRoCursor,
RoTransactionImpl as LmdbRoTransaction,
RwCursorImpl as LmdbRwCursor,
RwTransactionImpl as LmdbRwTransaction,
StatImpl as LmdbStat,
WriteFlagsImpl as LmdbWriteFlags,
};
pub use impl_safe::{
DatabaseFlagsImpl as SafeModeDatabaseFlags, DatabaseImpl as SafeModeDatabase,
EnvironmentBuilderImpl as SafeMode, EnvironmentFlagsImpl as SafeModeEnvironmentFlags,
EnvironmentImpl as SafeModeEnvironment, ErrorImpl as SafeModeError, InfoImpl as SafeModeInfo,
IterImpl as SafeModeIter, RoCursorImpl as SafeModeRoCursor,
RoTransactionImpl as SafeModeRoTransaction, RwCursorImpl as SafeModeRwCursor,
RwTransactionImpl as SafeModeRwTransaction, StatImpl as SafeModeStat,
DatabaseFlagsImpl as SafeModeDatabaseFlags,
DatabaseImpl as SafeModeDatabase,
EnvironmentBuilderImpl as SafeMode,
EnvironmentFlagsImpl as SafeModeEnvironmentFlags,
EnvironmentImpl as SafeModeEnvironment,
ErrorImpl as SafeModeError,
InfoImpl as SafeModeInfo,
IterImpl as SafeModeIter,
RoCursorImpl as SafeModeRoCursor,
RoTransactionImpl as SafeModeRoTransaction,
RwCursorImpl as SafeModeRwCursor,
RwTransactionImpl as SafeModeRwTransaction,
StatImpl as SafeModeStat,
WriteFlagsImpl as SafeModeWriteFlags,
};

View File

@ -21,14 +21,29 @@ mod stat;
mod transaction;
pub use arch_migrator::{
MigrateError as ArchMigrateError, MigrateResult as ArchMigrateResult, Migrator as ArchMigrator,
MigrateError as ArchMigrateError,
MigrateResult as ArchMigrateResult,
Migrator as ArchMigrator,
};
pub use cursor::{
RoCursorImpl,
RwCursorImpl,
};
pub use cursor::{RoCursorImpl, RwCursorImpl};
pub use database::DatabaseImpl;
pub use environment::{EnvironmentBuilderImpl, EnvironmentImpl};
pub use environment::{
EnvironmentBuilderImpl,
EnvironmentImpl,
};
pub use error::ErrorImpl;
pub use flags::{DatabaseFlagsImpl, EnvironmentFlagsImpl, WriteFlagsImpl};
pub use flags::{
DatabaseFlagsImpl,
EnvironmentFlagsImpl,
WriteFlagsImpl,
};
pub use info::InfoImpl;
pub use iter::IterImpl;
pub use stat::StatImpl;
pub use transaction::{RoTransactionImpl, RwTransactionImpl};
pub use transaction::{
RoTransactionImpl,
RwTransactionImpl,
};

View File

@ -7,8 +7,6 @@
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#![allow(dead_code)] // TODO: Get rid of unused struct members
#![allow(clippy::upper_case_acronyms)] // TODO: Consider renaming things like `BRANCH`
//! A utility for migrating data from one LMDB environment to another. Notably, this tool
//! can migrate data from an enviroment created with a different bit-depth than the
@ -58,18 +56,38 @@
//! variants identify specific kinds of migration failures.
use std::{
collections::{BTreeMap, HashMap},
collections::{
BTreeMap,
HashMap,
},
convert::TryFrom,
fs::File,
io::{Cursor, Read, Seek, SeekFrom, Write},
path::{Path, PathBuf},
io::{
Cursor,
Read,
Seek,
SeekFrom,
Write,
},
path::{
Path,
PathBuf,
},
rc::Rc,
str,
};
use bitflags::bitflags;
use byteorder::{LittleEndian, ReadBytesExt};
use lmdb::{DatabaseFlags, Environment, Transaction, WriteFlags};
use byteorder::{
LittleEndian,
ReadBytesExt,
};
use lmdb::{
DatabaseFlags,
Environment,
Transaction,
WriteFlags,
};
pub use super::arch_migrator_error::MigrateError;
@ -258,7 +276,9 @@ impl Page {
match Self::parse_page_header(&mut cursor, bits)? {
PageHeader::Regular {
mp_flags, pb_lower, ..
mp_flags,
pb_lower,
..
} => {
if mp_flags.contains(PageFlags::LEAF2) || mp_flags.contains(PageFlags::SUBP) {
// We don't yet support DUPFIXED and DUPSORT databases.
@ -277,21 +297,22 @@ impl Page {
} else {
Err(MigrateError::UnexpectedPageHeaderVariant)
}
}
PageHeader::Overflow { .. } => {
},
PageHeader::Overflow {
..
} => {
// There isn't anything to do, nor should we try to instantiate
// a page of this type, as we only access them when reading
// a value that is too large to fit into a leaf node.
Err(MigrateError::UnexpectedPageHeaderVariant)
}
},
}
}
fn parse_page_header(cursor: &mut Cursor<&[u8]>, bits: Bits) -> MigrateResult<PageHeader> {
let mp_pgno = cursor.read_uint::<LittleEndian>(bits.size())?;
let _mp_pad = cursor.read_u16::<LittleEndian>()?;
let mp_flags = PageFlags::from_bits(cursor.read_u16::<LittleEndian>()?)
.ok_or(MigrateError::InvalidPageBits)?;
let mp_flags = PageFlags::from_bits(cursor.read_u16::<LittleEndian>()?).ok_or(MigrateError::InvalidPageBits)?;
if mp_flags.contains(PageFlags::OVERFLOW) {
let pb_pages = cursor.read_u32::<LittleEndian>()?;
@ -312,7 +333,7 @@ impl Page {
}
}
fn parse_meta_data(cursor: &mut Cursor<&[u8]>, bits: Bits) -> MigrateResult<MetaData> {
fn parse_meta_data(mut cursor: &mut Cursor<&[u8]>, bits: Bits) -> MigrateResult<MetaData> {
cursor.seek(SeekFrom::Start(page_header_size(bits)))?;
Ok(MetaData {
@ -321,19 +342,15 @@ impl Page {
mm_address: cursor.read_uint::<LittleEndian>(bits.size())?,
mm_mapsize: cursor.read_uint::<LittleEndian>(bits.size())?,
mm_dbs: Databases {
free: Database::new(cursor, bits)?,
main: Database::new(cursor, bits)?,
free: Database::new(&mut cursor, bits)?,
main: Database::new(&mut cursor, bits)?,
},
mm_last_pg: cursor.read_uint::<LittleEndian>(bits.size())?,
mm_txnid: cursor.read_uint::<LittleEndian>(bits.size())?,
})
}
fn parse_leaf_nodes(
cursor: &mut Cursor<&[u8]>,
pb_lower: u16,
bits: Bits,
) -> MigrateResult<Vec<LeafNode>> {
fn parse_leaf_nodes(cursor: &mut Cursor<&[u8]>, pb_lower: u16, bits: Bits) -> MigrateResult<Vec<LeafNode>> {
cursor.set_position(page_header_size(bits));
let num_keys = Self::num_keys(pb_lower, bits);
let mp_ptrs = Self::parse_mp_ptrs(cursor, num_keys)?;
@ -354,8 +371,7 @@ impl Page {
let mn_lo = cursor.read_u16::<LittleEndian>()?;
let mn_hi = cursor.read_u16::<LittleEndian>()?;
let mn_flags = NodeFlags::from_bits(cursor.read_u16::<LittleEndian>()?)
.ok_or(MigrateError::InvalidNodeBits)?;
let mn_flags = NodeFlags::from_bits(cursor.read_u16::<LittleEndian>()?).ok_or(MigrateError::InvalidNodeBits)?;
let mn_ksize = cursor.read_u16::<LittleEndian>()?;
let start = usize::try_from(cursor.position())?;
@ -412,11 +428,7 @@ impl Page {
u32::from(mn_lo) + ((u32::from(mn_hi)) << 16)
}
fn parse_branch_nodes(
cursor: &mut Cursor<&[u8]>,
pb_lower: u16,
bits: Bits,
) -> MigrateResult<Vec<BranchNode>> {
fn parse_branch_nodes(cursor: &mut Cursor<&[u8]>, pb_lower: u16, bits: Bits) -> MigrateResult<Vec<BranchNode>> {
let num_keys = Self::num_keys(pb_lower, bits);
let mp_ptrs = Self::parse_mp_ptrs(cursor, num_keys)?;
@ -509,7 +521,10 @@ impl Migrator {
}
};
Ok(Migrator { file, bits })
Ok(Migrator {
file,
bits,
})
}
/// Dump the data in one of the databases in the LMDB environment. If the `database`
@ -532,9 +547,8 @@ impl Migrator {
let pairs;
if let Some(database) = database {
let subdbs = self.get_subdbs(root_page)?;
let database = subdbs
.get(database.as_bytes())
.ok_or_else(|| MigrateError::DatabaseNotFound(database.to_string()))?;
let database =
subdbs.get(database.as_bytes()).ok_or_else(|| MigrateError::DatabaseNotFound(database.to_string()))?;
let root_page_num = database.md_root;
let root_page = Rc::new(self.get_page(root_page_num)?);
pairs = self.get_pairs(root_page)?;
@ -545,7 +559,7 @@ impl Migrator {
out.write_all(b"VERSION=3\n")?;
out.write_all(b"format=bytevalue\n")?;
if let Some(database) = database {
writeln!(out, "database={database}")?;
writeln!(out, "database={}", database)?;
}
out.write_all(b"type=btree\n")?;
writeln!(out, "mapsize={}", meta_data.mm_mapsize)?;
@ -556,12 +570,12 @@ impl Migrator {
for (key, value) in pairs {
out.write_all(b" ")?;
for byte in key {
write!(out, "{byte:02x}")?;
write!(out, "{:02x}", byte)?;
}
out.write_all(b"\n")?;
out.write_all(b" ")?;
for byte in value {
write!(out, "{byte:02x}")?;
write!(out, "{:02x}", byte)?;
}
out.write_all(b"\n")?;
}
@ -600,7 +614,7 @@ impl Migrator {
// awaiting completion of an existing one.
env.create_db(None, meta_data.mm_dbs.main.md_flags)?;
for (subdb_name, subdb_info) in &subdbs {
env.create_db(Some(str::from_utf8(subdb_name)?), subdb_info.md_flags)?;
env.create_db(Some(str::from_utf8(&subdb_name)?), subdb_info.md_flags)?;
}
// Now open the read-write transaction that we'll use to migrate all the data.
@ -619,7 +633,7 @@ impl Migrator {
for (subdb_name, subdb_info) in &subdbs {
let root_page = Rc::new(self.get_page(subdb_info.md_root)?);
let pairs = self.get_pairs(root_page)?;
let db = env.open_db(Some(str::from_utf8(subdb_name)?))?;
let db = env.open_db(Some(str::from_utf8(&subdb_name)?))?;
for (key, value) in pairs {
// If we knew that the target database was empty, we could specify
// WriteFlags::APPEND to speed up the migration.
@ -642,17 +656,22 @@ impl Migrator {
for branch in nodes {
pages.push(Rc::new(self.get_page(branch.mp_pgno)?));
}
}
},
Page::LEAF(nodes) => {
for leaf in nodes {
if let LeafNode::SubData { key, db, .. } = leaf {
if let LeafNode::SubData {
key,
db,
..
} = leaf
{
subdbs.insert(key.to_vec(), db.clone());
};
}
}
},
_ => {
return Err(MigrateError::UnexpectedPageVariant);
}
},
}
}
@ -669,13 +688,17 @@ impl Migrator {
for branch in nodes {
pages.push(Rc::new(self.get_page(branch.mp_pgno)?));
}
}
},
Page::LEAF(nodes) => {
for leaf in nodes {
match leaf {
LeafNode::Regular { key, value, .. } => {
LeafNode::Regular {
key,
value,
..
} => {
pairs.insert(key.to_vec(), value.to_vec());
}
},
LeafNode::BigData {
mv_size,
key,
@ -686,13 +709,14 @@ impl Migrator {
// migration by waiting to read big data until it's time
// to write it to the new database.
let value = self.read_data(
*overflow_pgno * u64::from(PAGESIZE)
+ page_header_size(self.bits),
*overflow_pgno * u64::from(PAGESIZE) + page_header_size(self.bits),
*mv_size as usize,
)?;
pairs.insert(key.to_vec(), value);
}
LeafNode::SubData { .. } => {
},
LeafNode::SubData {
..
} => {
// We don't include subdatabase leaves in pairs, since
// there's no architecture-neutral representation of them,
// and in any case they're meta-data that should get
@ -702,13 +726,13 @@ impl Migrator {
// produced by `mdb_dump`, however, we could allow
// consumers to specify that they'd like to include these
// records.
}
},
};
}
}
},
_ => {
return Err(MigrateError::UnexpectedPageVariant);
}
},
}
}
@ -723,10 +747,7 @@ impl Migrator {
}
fn get_page(&mut self, page_no: u64) -> MigrateResult<Page> {
Page::new(
self.read_data(page_no * u64::from(PAGESIZE), usize::from(PAGESIZE))?,
self.bits,
)
Page::new(self.read_data(page_no * u64::from(PAGESIZE), usize::from(PAGESIZE))?, self.bits)
}
fn get_meta_data(&mut self) -> MigrateResult<MetaData> {
@ -746,7 +767,7 @@ impl Migrator {
return Err(MigrateError::InvalidDataVersion);
}
Ok(meta)
}
},
_ => Err(MigrateError::UnexpectedPageVariant),
}
}
@ -756,10 +777,20 @@ impl Migrator {
mod tests {
use super::*;
use std::{env, fs, mem::size_of};
use std::{
env,
fs,
mem::size_of,
};
use lmdb::{Environment, Error as LmdbError};
use tempfile::{tempdir, tempfile};
use lmdb::{
Environment,
Error as LmdbError,
};
use tempfile::{
tempdir,
tempfile,
};
fn compare_files(ref_file: &mut File, new_file: &mut File) -> MigrateResult<()> {
ref_file.seek(SeekFrom::Start(0))?;
@ -770,15 +801,17 @@ mod tests {
loop {
match ref_file.read(ref_buf) {
Err(err) => panic!("{}", err),
Ok(ref_len) => match new_file.read(new_buf) {
Err(err) => panic!("{}", err),
Ok(new_len) => {
assert_eq!(ref_len, new_len);
if ref_len == 0 {
break;
};
assert_eq!(ref_buf[0..ref_len], new_buf[0..new_len]);
Err(err) => panic!(err),
Ok(ref_len) => {
match new_file.read(new_buf) {
Err(err) => panic!(err),
Ok(new_len) => {
assert_eq!(ref_len, new_len);
if ref_len == 0 {
break;
};
assert_eq!(ref_buf[0..ref_len], new_buf[0..new_len]);
},
}
},
}
@ -820,9 +853,7 @@ mod tests {
migrator.dump(Some("subdb"), &new_dump_file)?;
// Open the reference dump file.
let ref_dump_file_path: PathBuf = [cwd, "tests", "envs", "ref_dump_subdb.txt"]
.iter()
.collect();
let ref_dump_file_path: PathBuf = [cwd, "tests", "envs", "ref_dump_subdb.txt"].iter().collect();
let mut ref_dump_file = File::open(ref_dump_file_path)?;
// Compare the new dump file to the reference dump file.
@ -864,9 +895,7 @@ mod tests {
migrator.dump(Some("subdb"), &new_dump_file)?;
// Open the reference dump file.
let ref_dump_file_path: PathBuf = [cwd, "tests", "envs", "ref_dump_subdb.txt"]
.iter()
.collect();
let ref_dump_file_path: PathBuf = [cwd, "tests", "envs", "ref_dump_subdb.txt"].iter().collect();
let mut ref_dump_file = File::open(ref_dump_file_path)?;
// Compare the new dump file to the reference dump file.
@ -887,14 +916,12 @@ mod tests {
migrator.migrate(new_env.path())?;
// Dump data from the new env to a new dump file.
let mut migrator = Migrator::new(new_env.path())?;
let mut migrator = Migrator::new(&new_env.path())?;
let mut new_dump_file = tempfile()?;
migrator.dump(Some("subdb"), &new_dump_file)?;
// Open the reference dump file.
let ref_dump_file_path: PathBuf = [cwd, "tests", "envs", "ref_dump_subdb.txt"]
.iter()
.collect();
let ref_dump_file_path: PathBuf = [cwd, "tests", "envs", "ref_dump_subdb.txt"].iter().collect();
let mut ref_dump_file = File::open(ref_dump_file_path)?;
// Compare the new dump file to the reference dump file.
@ -915,14 +942,12 @@ mod tests {
migrator.migrate(new_env.path())?;
// Dump data from the new env to a new dump file.
let mut migrator = Migrator::new(new_env.path())?;
let mut migrator = Migrator::new(&new_env.path())?;
let mut new_dump_file = tempfile()?;
migrator.dump(Some("subdb"), &new_dump_file)?;
// Open the reference dump file.
let ref_dump_file_path: PathBuf = [cwd, "tests", "envs", "ref_dump_subdb.txt"]
.iter()
.collect();
let ref_dump_file_path: PathBuf = [cwd, "tests", "envs", "ref_dump_subdb.txt"].iter().collect();
let mut ref_dump_file = File::open(ref_dump_file_path)?;
// Compare the new dump file to the reference dump file.
@ -944,18 +969,12 @@ mod tests {
let test_env_path: PathBuf = [cwd, "tests", "envs", test_env_name].iter().collect();
let old_env = tempdir()?;
fs::copy(
test_env_path.join("data.mdb"),
old_env.path().join("data.mdb"),
)?;
fs::copy(
test_env_path.join("lock.mdb"),
old_env.path().join("lock.mdb"),
)?;
fs::copy(test_env_path.join("data.mdb"), old_env.path().join("data.mdb"))?;
fs::copy(test_env_path.join("lock.mdb"), old_env.path().join("lock.mdb"))?;
// Confirm that it isn't possible to open the old environment with LMDB.
assert_eq!(
match Environment::new().open(old_env.path()) {
match Environment::new().open(&old_env.path()) {
Err(err) => err,
_ => panic!("opening the environment should have failed"),
},
@ -964,18 +983,16 @@ mod tests {
// Migrate data from the old env to a new one.
let new_env = tempdir()?;
let mut migrator = Migrator::new(old_env.path())?;
let mut migrator = Migrator::new(&old_env.path())?;
migrator.migrate(new_env.path())?;
// Dump data from the new env to a new dump file.
let mut migrator = Migrator::new(new_env.path())?;
let mut migrator = Migrator::new(&new_env.path())?;
let mut new_dump_file = tempfile()?;
migrator.dump(Some("subdb"), &new_dump_file)?;
// Open the reference dump file.
let ref_dump_file_path: PathBuf = [cwd, "tests", "envs", "ref_dump_subdb.txt"]
.iter()
.collect();
let ref_dump_file_path: PathBuf = [cwd, "tests", "envs", "ref_dump_subdb.txt"].iter().collect();
let mut ref_dump_file = File::open(ref_dump_file_path)?;
// Compare the new dump file to the reference dump file.
@ -983,15 +1000,9 @@ mod tests {
// Overwrite the old env's files with the new env's files and confirm that it's now
// possible to open the old env with LMDB.
fs::copy(
new_env.path().join("data.mdb"),
old_env.path().join("data.mdb"),
)?;
fs::copy(
new_env.path().join("lock.mdb"),
old_env.path().join("lock.mdb"),
)?;
assert!(Environment::new().open(old_env.path()).is_ok());
fs::copy(new_env.path().join("data.mdb"), old_env.path().join("data.mdb"))?;
fs::copy(new_env.path().join("lock.mdb"), old_env.path().join("lock.mdb"))?;
assert!(Environment::new().open(&old_env.path()).is_ok());
Ok(())
}

View File

@ -8,7 +8,11 @@
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
use std::{io, num, str};
use std::{
io,
num,
str,
};
use thiserror::Error;

View File

@ -10,18 +10,32 @@
use std::{
fs,
path::{Path, PathBuf},
path::{
Path,
PathBuf,
},
};
use lmdb::Error as LmdbError;
use super::{
DatabaseFlagsImpl, DatabaseImpl, EnvironmentFlagsImpl, ErrorImpl, InfoImpl, RoTransactionImpl,
RwTransactionImpl, StatImpl,
DatabaseFlagsImpl,
DatabaseImpl,
EnvironmentFlagsImpl,
ErrorImpl,
InfoImpl,
RoTransactionImpl,
RwTransactionImpl,
StatImpl,
};
use crate::backend::traits::{
BackendEnvironment, BackendEnvironmentBuilder, BackendInfo, BackendIter, BackendRoCursor,
BackendRoCursorTransaction, BackendStat,
BackendEnvironment,
BackendEnvironmentBuilder,
BackendInfo,
BackendIter,
BackendRoCursor,
BackendRoCursorTransaction,
BackendStat,
};
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
@ -98,7 +112,7 @@ impl<'b> BackendEnvironmentBuilder<'b> for EnvironmentBuilderImpl {
if !path.is_file() {
return Err(ErrorImpl::UnsuitableEnvironmentPath(path.into()));
}
}
},
EnvironmentPathType::SubDir => {
if !path.is_dir() {
if !self.make_dir_if_needed {
@ -106,21 +120,12 @@ impl<'b> BackendEnvironmentBuilder<'b> for EnvironmentBuilderImpl {
}
fs::create_dir_all(path)?;
}
}
},
}
self.builder
.open(path)
.map_err(ErrorImpl::LmdbError)
.and_then(|lmdbenv| {
EnvironmentImpl::new(
path,
self.env_path_type,
self.env_lock_type,
self.env_db_type,
lmdbenv,
)
})
self.builder.open(path).map_err(ErrorImpl::LmdbError).and_then(|lmdbenv| {
EnvironmentImpl::new(path, self.env_path_type, self.env_lock_type, self.env_db_type, lmdbenv)
})
}
}
@ -182,54 +187,33 @@ impl<'e> BackendEnvironment<'e> for EnvironmentImpl {
if self.env_db_type == EnvironmentDefaultDbType::SingleDatabase {
return Ok(vec![None]);
}
let db = self
.lmdbenv
.open_db(None)
.map(DatabaseImpl)
.map_err(ErrorImpl::LmdbError)?;
let db = self.lmdbenv.open_db(None).map(DatabaseImpl).map_err(ErrorImpl::LmdbError)?;
let reader = self.begin_ro_txn()?;
let cursor = reader.open_ro_cursor(&db)?;
let mut iter = cursor.into_iter();
let mut store = vec![];
while let Some(result) = iter.next() {
let (key, _) = result?;
let name = String::from_utf8(key.to_owned())
.map_err(|_| ErrorImpl::LmdbError(lmdb::Error::Corrupted))?;
let name = String::from_utf8(key.to_owned()).map_err(|_| ErrorImpl::LmdbError(lmdb::Error::Corrupted))?;
store.push(Some(name));
}
Ok(store)
}
fn open_db(&self, name: Option<&str>) -> Result<Self::Database, Self::Error> {
self.lmdbenv
.open_db(name)
.map(DatabaseImpl)
.map_err(ErrorImpl::LmdbError)
self.lmdbenv.open_db(name).map(DatabaseImpl).map_err(ErrorImpl::LmdbError)
}
fn create_db(
&self,
name: Option<&str>,
flags: Self::Flags,
) -> Result<Self::Database, Self::Error> {
self.lmdbenv
.create_db(name, flags.0)
.map(DatabaseImpl)
.map_err(ErrorImpl::LmdbError)
fn create_db(&self, name: Option<&str>, flags: Self::Flags) -> Result<Self::Database, Self::Error> {
self.lmdbenv.create_db(name, flags.0).map(DatabaseImpl).map_err(ErrorImpl::LmdbError)
}
fn begin_ro_txn(&'e self) -> Result<Self::RoTransaction, Self::Error> {
self.lmdbenv
.begin_ro_txn()
.map(RoTransactionImpl)
.map_err(ErrorImpl::LmdbError)
self.lmdbenv.begin_ro_txn().map(RoTransactionImpl).map_err(ErrorImpl::LmdbError)
}
fn begin_rw_txn(&'e self) -> Result<Self::RwTransaction, Self::Error> {
self.lmdbenv
.begin_rw_txn()
.map(RwTransactionImpl)
.map_err(ErrorImpl::LmdbError)
self.lmdbenv.begin_rw_txn().map(RwTransactionImpl).map_err(ErrorImpl::LmdbError)
}
fn sync(&self, force: bool) -> Result<(), Self::Error> {
@ -237,17 +221,11 @@ impl<'e> BackendEnvironment<'e> for EnvironmentImpl {
}
fn stat(&self) -> Result<Self::Stat, Self::Error> {
self.lmdbenv
.stat()
.map(StatImpl)
.map_err(ErrorImpl::LmdbError)
self.lmdbenv.stat().map(StatImpl).map_err(ErrorImpl::LmdbError)
}
fn info(&self) -> Result<Self::Info, Self::Error> {
self.lmdbenv
.info()
.map(InfoImpl)
.map_err(ErrorImpl::LmdbError)
self.lmdbenv.info().map(InfoImpl).map_err(ErrorImpl::LmdbError)
}
fn freelist(&self) -> Result<usize, Self::Error> {
@ -269,9 +247,7 @@ impl<'e> BackendEnvironment<'e> for EnvironmentImpl {
}
fn set_map_size(&self, size: usize) -> Result<(), Self::Error> {
self.lmdbenv
.set_map_size(size)
.map_err(ErrorImpl::LmdbError)
self.lmdbenv.set_map_size(size).map_err(ErrorImpl::LmdbError)
}
fn get_files_on_disk(&self) -> Vec<PathBuf> {

View File

@ -8,9 +8,16 @@
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
use std::{fmt, io, path::PathBuf};
use std::{
fmt,
io,
path::PathBuf,
};
use crate::{backend::traits::BackendError, error::StoreError};
use crate::{
backend::traits::BackendError,
error::StoreError,
};
#[derive(Debug)]
pub enum ErrorImpl {
@ -42,9 +49,7 @@ impl Into<StoreError> for ErrorImpl {
ErrorImpl::LmdbError(lmdb::Error::DbsFull) => StoreError::DbsFull,
ErrorImpl::LmdbError(lmdb::Error::ReadersFull) => StoreError::ReadersFull,
ErrorImpl::LmdbError(error) => StoreError::LmdbError(error),
ErrorImpl::UnsuitableEnvironmentPath(path) => {
StoreError::UnsuitableEnvironmentPath(path)
}
ErrorImpl::UnsuitableEnvironmentPath(path) => StoreError::UnsuitableEnvironmentPath(path),
ErrorImpl::IoError(error) => StoreError::IoError(error),
}
}

View File

@ -9,8 +9,17 @@
// specific language governing permissions and limitations under the License.
use crate::backend::{
common::{DatabaseFlags, EnvironmentFlags, WriteFlags},
traits::{BackendDatabaseFlags, BackendEnvironmentFlags, BackendFlags, BackendWriteFlags},
common::{
DatabaseFlags,
EnvironmentFlags,
WriteFlags,
},
traits::{
BackendDatabaseFlags,
BackendEnvironmentFlags,
BackendFlags,
BackendWriteFlags,
},
};
#[derive(Debug, Eq, PartialEq, Copy, Clone, Default)]

View File

@ -22,12 +22,12 @@ pub struct IterImpl<'i, C> {
}
impl<'i, C> IterImpl<'i, C> {
pub(crate) fn new(
mut cursor: C,
to_iter: impl FnOnce(&mut C) -> lmdb::Iter<'i>,
) -> IterImpl<'i, C> {
pub(crate) fn new(mut cursor: C, to_iter: impl FnOnce(&mut C) -> lmdb::Iter<'i>) -> IterImpl<'i, C> {
let iter = to_iter(&mut cursor);
IterImpl { cursor, iter }
IterImpl {
cursor,
iter,
}
}
}

View File

@ -10,9 +10,16 @@
use lmdb::Transaction;
use super::{DatabaseImpl, ErrorImpl, RoCursorImpl, WriteFlagsImpl};
use super::{
DatabaseImpl,
ErrorImpl,
RoCursorImpl,
WriteFlagsImpl,
};
use crate::backend::traits::{
BackendRoCursorTransaction, BackendRoTransaction, BackendRwCursorTransaction,
BackendRoCursorTransaction,
BackendRoTransaction,
BackendRwCursorTransaction,
BackendRwTransaction,
};
@ -36,10 +43,7 @@ impl<'t> BackendRoCursorTransaction<'t> for RoTransactionImpl<'t> {
type RoCursor = RoCursorImpl<'t>;
fn open_ro_cursor(&'t self, db: &Self::Database) -> Result<Self::RoCursor, Self::Error> {
self.0
.open_ro_cursor(db.0)
.map(RoCursorImpl)
.map_err(ErrorImpl::LmdbError)
self.0.open_ro_cursor(db.0).map(RoCursorImpl).map_err(ErrorImpl::LmdbError)
}
}
@ -55,16 +59,8 @@ impl<'t> BackendRwTransaction for RwTransactionImpl<'t> {
self.0.get(db.0, &key).map_err(ErrorImpl::LmdbError)
}
fn put(
&mut self,
db: &Self::Database,
key: &[u8],
value: &[u8],
flags: Self::Flags,
) -> Result<(), Self::Error> {
self.0
.put(db.0, &key, &value, flags.0)
.map_err(ErrorImpl::LmdbError)
fn put(&mut self, db: &Self::Database, key: &[u8], value: &[u8], flags: Self::Flags) -> Result<(), Self::Error> {
self.0.put(db.0, &key, &value, flags.0).map_err(ErrorImpl::LmdbError)
}
#[cfg(not(feature = "db-dup-sort"))]
@ -73,12 +69,7 @@ impl<'t> BackendRwTransaction for RwTransactionImpl<'t> {
}
#[cfg(feature = "db-dup-sort")]
fn del(
&mut self,
db: &Self::Database,
key: &[u8],
value: Option<&[u8]>,
) -> Result<(), Self::Error> {
fn del(&mut self, db: &Self::Database, key: &[u8], value: Option<&[u8]>) -> Result<(), Self::Error> {
self.0.del(db.0, &key, value).map_err(ErrorImpl::LmdbError)
}
@ -99,9 +90,6 @@ impl<'t> BackendRwCursorTransaction<'t> for RwTransactionImpl<'t> {
type RoCursor = RoCursorImpl<'t>;
fn open_ro_cursor(&'t self, db: &Self::Database) -> Result<Self::RoCursor, Self::Error> {
self.0
.open_ro_cursor(db.0)
.map(RoCursorImpl)
.map_err(ErrorImpl::LmdbError)
self.0.open_ro_cursor(db.0).map(RoCursorImpl).map_err(ErrorImpl::LmdbError)
}
}

View File

@ -19,12 +19,25 @@ mod snapshot;
mod stat;
mod transaction;
pub use cursor::{RoCursorImpl, RwCursorImpl};
pub use cursor::{
RoCursorImpl,
RwCursorImpl,
};
pub use database::DatabaseImpl;
pub use environment::{EnvironmentBuilderImpl, EnvironmentImpl};
pub use environment::{
EnvironmentBuilderImpl,
EnvironmentImpl,
};
pub use error::ErrorImpl;
pub use flags::{DatabaseFlagsImpl, EnvironmentFlagsImpl, WriteFlagsImpl};
pub use flags::{
DatabaseFlagsImpl,
EnvironmentFlagsImpl,
WriteFlagsImpl,
};
pub use info::InfoImpl;
pub use iter::IterImpl;
pub use stat::StatImpl;
pub use transaction::{RoTransactionImpl, RwTransactionImpl};
pub use transaction::{
RoTransactionImpl,
RwTransactionImpl,
};

View File

@ -8,7 +8,10 @@
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
use super::{snapshot::Snapshot, IterImpl};
use super::{
snapshot::Snapshot,
IterImpl,
};
use crate::backend::traits::BackendRoCursor;
#[derive(Debug)]
@ -26,18 +29,14 @@ impl<'c> BackendRoCursor<'c> for RoCursorImpl<'c> {
where
K: AsRef<[u8]> + 'c,
{
IterImpl(Box::new(
self.0.iter().skip_while(move |&(k, _)| k < key.as_ref()),
))
IterImpl(Box::new(self.0.iter().skip_while(move |&(k, _)| k < key.as_ref())))
}
fn into_iter_dup_of<K>(self, key: K) -> Self::Iter
where
K: AsRef<[u8]> + 'c,
{
IterImpl(Box::new(
self.0.iter().filter(move |&(k, _)| k == key.as_ref()),
))
IterImpl(Box::new(self.0.iter().filter(move |&(k, _)| k == key.as_ref())))
}
}
@ -46,10 +45,7 @@ impl<'c> BackendRoCursor<'c> for RoCursorImpl<'c> {
type Iter = IterImpl<'c>;
fn into_iter(self) -> Self::Iter {
let flattened = self
.0
.iter()
.flat_map(|(key, values)| values.map(move |value| (key, value)));
let flattened = self.0.iter().flat_map(|(key, values)| values.map(move |value| (key, value)));
IterImpl(Box::new(flattened))
}

View File

@ -9,9 +9,15 @@
// specific language governing permissions and limitations under the License.
use id_arena::Id;
use serde_derive::{Deserialize, Serialize};
use serde_derive::{
Deserialize,
Serialize,
};
use super::{snapshot::Snapshot, DatabaseFlagsImpl};
use super::{
snapshot::Snapshot,
DatabaseFlagsImpl,
};
use crate::backend::traits::BackendDatabase;
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]

View File

@ -13,18 +13,36 @@ use std::{
collections::HashMap,
fs,
ops::DerefMut,
path::{Path, PathBuf},
sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard},
path::{
Path,
PathBuf,
},
sync::{
Arc,
RwLock,
RwLockReadGuard,
RwLockWriteGuard,
},
};
use id_arena::Arena;
use log::warn;
use super::{
database::Database, DatabaseFlagsImpl, DatabaseImpl, EnvironmentFlagsImpl, ErrorImpl, InfoImpl,
RoTransactionImpl, RwTransactionImpl, StatImpl,
database::Database,
DatabaseFlagsImpl,
DatabaseImpl,
EnvironmentFlagsImpl,
ErrorImpl,
InfoImpl,
RoTransactionImpl,
RwTransactionImpl,
StatImpl,
};
use crate::backend::traits::{
BackendEnvironment,
BackendEnvironmentBuilder,
};
use crate::backend::traits::{BackendEnvironment, BackendEnvironmentBuilder};
const DEFAULT_DB_FILENAME: &str = "data.safe.bin";
@ -99,13 +117,7 @@ impl<'b> BackendEnvironmentBuilder<'b> for EnvironmentBuilderImpl {
}
fs::create_dir_all(path)?;
}
let mut env = EnvironmentImpl::new(
path,
self.flags,
self.max_readers,
self.max_dbs,
self.map_size,
)?;
let mut env = EnvironmentImpl::new(path, self.flags, self.max_readers, self.max_dbs, self.map_size)?;
env.read_from_disk(self.discard_if_corrupted)?;
Ok(env)
}
@ -144,21 +156,14 @@ pub struct EnvironmentImpl {
impl EnvironmentImpl {
fn serialize(&self) -> Result<Vec<u8>, ErrorImpl> {
let dbs = self.dbs.read().map_err(|_| ErrorImpl::EnvPoisonError)?;
let data: HashMap<_, _> = dbs
.name_map
.iter()
.map(|(name, id)| (name, &dbs.arena[id.0]))
.collect();
let data: HashMap<_, _> = dbs.name_map.iter().map(|(name, id)| (name, &dbs.arena[id.0])).collect();
Ok(bincode::serialize(&data)?)
}
fn deserialize(
bytes: &[u8],
discard_if_corrupted: bool,
) -> Result<(DatabaseArena, DatabaseNameMap), ErrorImpl> {
fn deserialize(bytes: &[u8], discard_if_corrupted: bool) -> Result<(DatabaseArena, DatabaseNameMap), ErrorImpl> {
let mut arena = DatabaseArena::new();
let mut name_map = HashMap::new();
let data: HashMap<_, _> = match bincode::deserialize(bytes) {
let data: HashMap<_, _> = match bincode::deserialize(&bytes) {
Err(_) if discard_if_corrupted => Ok(HashMap::new()),
result => result,
}?;
@ -208,7 +213,10 @@ impl EnvironmentImpl {
return Ok(());
};
let (arena, name_map) = Self::deserialize(&fs::read(&path)?, discard_if_corrupted)?;
self.dbs = RwLock::new(EnvironmentDbs { arena, name_map });
self.dbs = RwLock::new(EnvironmentDbs {
arena,
name_map,
});
Ok(())
}
@ -255,26 +263,20 @@ impl<'e> BackendEnvironment<'e> for EnvironmentImpl {
Ok(*db)
}
fn create_db(
&self,
name: Option<&str>,
flags: Self::Flags,
) -> Result<Self::Database, Self::Error> {
fn create_db(&self, name: Option<&str>, flags: Self::Flags) -> Result<Self::Database, Self::Error> {
if Arc::strong_count(&self.ro_txns) > 1 {
return Err(ErrorImpl::DbsIllegalOpen);
}
// TOOD: don't reallocate `name`.
let key = name.map(String::from);
let mut dbs = self.dbs.write().map_err(|_| ErrorImpl::EnvPoisonError)?;
if dbs.name_map.keys().filter_map(|k| k.as_ref()).count() >= self.max_dbs && name.is_some() {
if dbs.name_map.keys().filter_map(|k| k.as_ref()).count() >= self.max_dbs && name != None {
return Err(ErrorImpl::DbsFull);
}
let parts = EnvironmentDbsRefMut::from(dbs.deref_mut());
let arena = parts.arena;
let name_map = parts.name_map;
let id = name_map
.entry(key)
.or_insert_with(|| DatabaseImpl(arena.alloc(Database::new(Some(flags), None))));
let id = name_map.entry(key).or_insert_with(|| DatabaseImpl(arena.alloc(Database::new(Some(flags), None))));
Ok(*id)
}
@ -309,10 +311,7 @@ impl<'e> BackendEnvironment<'e> for EnvironmentImpl {
}
fn set_map_size(&self, size: usize) -> Result<(), Self::Error> {
warn!(
"`set_map_size({})` is ignored by this storage backend.",
size
);
warn!("`set_map_size({})` is ignored by this storage backend.", size);
Ok(())
}
@ -321,6 +320,6 @@ impl<'e> BackendEnvironment<'e> for EnvironmentImpl {
// they're both currently unimplemented with this storage backend.
let mut db_filename = self.path.clone();
db_filename.push(DEFAULT_DB_FILENAME);
vec![db_filename]
return vec![db_filename];
}
}

View File

@ -8,11 +8,18 @@
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
use std::{fmt, io, path::PathBuf};
use std::{
fmt,
io,
path::PathBuf,
};
use bincode::Error as BincodeError;
use crate::{backend::traits::BackendError, error::StoreError};
use crate::{
backend::traits::BackendError,
error::StoreError,
};
#[derive(Debug)]
pub enum ErrorImpl {
@ -38,9 +45,7 @@ impl fmt::Display for ErrorImpl {
ErrorImpl::DbsIllegalOpen => write!(fmt, "DbIllegalOpen (safe mode)"),
ErrorImpl::DbNotFoundError => write!(fmt, "DbNotFoundError (safe mode)"),
ErrorImpl::DbIsForeignError => write!(fmt, "DbIsForeignError (safe mode)"),
ErrorImpl::UnsuitableEnvironmentPath(_) => {
write!(fmt, "UnsuitableEnvironmentPath (safe mode)")
}
ErrorImpl::UnsuitableEnvironmentPath(_) => write!(fmt, "UnsuitableEnvironmentPath (safe mode)"),
ErrorImpl::IoError(e) => e.fmt(fmt),
ErrorImpl::BincodeError(e) => e.fmt(fmt),
}
@ -57,9 +62,7 @@ impl Into<StoreError> for ErrorImpl {
ErrorImpl::KeyValuePairNotFound => StoreError::KeyValuePairNotFound,
ErrorImpl::BincodeError(_) => StoreError::FileInvalid,
ErrorImpl::DbsFull => StoreError::DbsFull,
ErrorImpl::UnsuitableEnvironmentPath(path) => {
StoreError::UnsuitableEnvironmentPath(path)
}
ErrorImpl::UnsuitableEnvironmentPath(path) => StoreError::UnsuitableEnvironmentPath(path),
ErrorImpl::IoError(error) => StoreError::IoError(error),
_ => StoreError::SafeModeError(self),
}

View File

@ -9,11 +9,23 @@
// specific language governing permissions and limitations under the License.
use bitflags::bitflags;
use serde_derive::{Deserialize, Serialize};
use serde_derive::{
Deserialize,
Serialize,
};
use crate::backend::{
common::{DatabaseFlags, EnvironmentFlags, WriteFlags},
traits::{BackendDatabaseFlags, BackendEnvironmentFlags, BackendFlags, BackendWriteFlags},
common::{
DatabaseFlags,
EnvironmentFlags,
WriteFlags,
},
traits::{
BackendDatabaseFlags,
BackendEnvironmentFlags,
BackendFlags,
BackendWriteFlags,
},
};
bitflags! {

View File

@ -9,11 +9,17 @@
// specific language governing permissions and limitations under the License.
use std::{
collections::{BTreeMap, BTreeSet},
collections::{
BTreeMap,
BTreeSet,
},
sync::Arc,
};
use serde_derive::{Deserialize, Serialize};
use serde_derive::{
Deserialize,
Serialize,
};
use super::DatabaseFlagsImpl;
@ -32,7 +38,7 @@ pub struct Snapshot {
impl Snapshot {
pub(crate) fn new(flags: Option<DatabaseFlagsImpl>) -> Snapshot {
Snapshot {
flags: flags.unwrap_or_default(),
flags: flags.unwrap_or_else(DatabaseFlagsImpl::default),
map: Default::default(),
}
}
@ -63,19 +69,14 @@ impl Snapshot {
}
pub(crate) fn iter(&self) -> impl Iterator<Item = (&[u8], &[u8])> {
self.map
.iter()
.map(|(key, value)| (key.as_ref(), value.as_ref()))
self.map.iter().map(|(key, value)| (key.as_ref(), value.as_ref()))
}
}
#[cfg(feature = "db-dup-sort")]
impl Snapshot {
pub(crate) fn get(&self, key: &[u8]) -> Option<&[u8]> {
self.map
.get(key)
.and_then(|v| v.iter().next())
.map(|v| v.as_ref())
self.map.get(key).and_then(|v| v.iter().next()).map(|v| v.as_ref())
}
pub(crate) fn put(&mut self, key: &[u8], value: &[u8]) {
@ -85,11 +86,11 @@ impl Snapshot {
let mut values = BTreeSet::new();
values.insert(Box::from(value));
map.insert(Box::from(key), values);
}
},
Some(values) => {
values.clear();
values.insert(Box::from(value));
}
},
}
}
@ -101,14 +102,12 @@ impl Snapshot {
let was_empty = values.is_empty();
values.clear();
Some(()).filter(|_| !was_empty)
}
},
}
}
pub(crate) fn iter(&self) -> impl Iterator<Item = (&[u8], impl Iterator<Item = &[u8]>)> {
self.map
.iter()
.map(|(key, values)| (key.as_ref(), values.iter().map(|value| value.as_ref())))
self.map.iter().map(|(key, values)| (key.as_ref(), values.iter().map(|value| value.as_ref())))
}
}
@ -121,10 +120,10 @@ impl Snapshot {
let mut values = BTreeSet::new();
values.insert(Box::from(value));
map.insert(Box::from(key), values);
}
},
Some(values) => {
values.insert(Box::from(value));
}
},
}
}
@ -135,7 +134,7 @@ impl Snapshot {
Some(values) => {
let was_removed = values.remove(value);
Some(()).filter(|_| was_removed)
}
},
}
}
}

View File

@ -7,15 +7,24 @@
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#![allow(dead_code)] // TODO: Get rid of unused struct members
use std::{collections::HashMap, sync::Arc};
use std::{
collections::HashMap,
sync::Arc,
};
use super::{
snapshot::Snapshot, DatabaseImpl, EnvironmentImpl, ErrorImpl, RoCursorImpl, WriteFlagsImpl,
snapshot::Snapshot,
DatabaseImpl,
EnvironmentImpl,
ErrorImpl,
RoCursorImpl,
WriteFlagsImpl,
};
use crate::backend::traits::{
BackendRoCursorTransaction, BackendRoTransaction, BackendRwCursorTransaction,
BackendRoCursorTransaction,
BackendRoTransaction,
BackendRwCursorTransaction,
BackendRwTransaction,
};
@ -27,16 +36,8 @@ pub struct RoTransactionImpl<'t> {
}
impl<'t> RoTransactionImpl<'t> {
pub(crate) fn new(
env: &'t EnvironmentImpl,
idx: Arc<()>,
) -> Result<RoTransactionImpl<'t>, ErrorImpl> {
let snapshots = env
.dbs()?
.arena
.iter()
.map(|(id, db)| (DatabaseImpl(id), db.snapshot()))
.collect();
pub(crate) fn new(env: &'t EnvironmentImpl, idx: Arc<()>) -> Result<RoTransactionImpl<'t>, ErrorImpl> {
let snapshots = env.dbs()?.arena.iter().map(|(id, db)| (DatabaseImpl(id), db.snapshot())).collect();
Ok(RoTransactionImpl {
env,
snapshots,
@ -50,8 +51,8 @@ impl<'t> BackendRoTransaction for RoTransactionImpl<'t> {
type Error = ErrorImpl;
fn get(&self, db: &Self::Database, key: &[u8]) -> Result<&[u8], Self::Error> {
let snapshot = self.snapshots.get(db).ok_or(ErrorImpl::DbIsForeignError)?;
snapshot.get(key).ok_or(ErrorImpl::KeyValuePairNotFound)
let snapshot = self.snapshots.get(db).ok_or_else(|| ErrorImpl::DbIsForeignError)?;
snapshot.get(key).ok_or_else(|| ErrorImpl::KeyValuePairNotFound)
}
fn abort(self) {
@ -63,7 +64,7 @@ impl<'t> BackendRoCursorTransaction<'t> for RoTransactionImpl<'t> {
type RoCursor = RoCursorImpl<'t>;
fn open_ro_cursor(&'t self, db: &Self::Database) -> Result<Self::RoCursor, Self::Error> {
let snapshot = self.snapshots.get(db).ok_or(ErrorImpl::DbIsForeignError)?;
let snapshot = self.snapshots.get(db).ok_or_else(|| ErrorImpl::DbIsForeignError)?;
Ok(RoCursorImpl(snapshot))
}
}
@ -76,16 +77,8 @@ pub struct RwTransactionImpl<'t> {
}
impl<'t> RwTransactionImpl<'t> {
pub(crate) fn new(
env: &'t EnvironmentImpl,
idx: Arc<()>,
) -> Result<RwTransactionImpl<'t>, ErrorImpl> {
let snapshots = env
.dbs()?
.arena
.iter()
.map(|(id, db)| (DatabaseImpl(id), db.snapshot()))
.collect();
pub(crate) fn new(env: &'t EnvironmentImpl, idx: Arc<()>) -> Result<RwTransactionImpl<'t>, ErrorImpl> {
let snapshots = env.dbs()?.arena.iter().map(|(id, db)| (DatabaseImpl(id), db.snapshot())).collect();
Ok(RwTransactionImpl {
env,
snapshots,
@ -100,39 +93,21 @@ impl<'t> BackendRwTransaction for RwTransactionImpl<'t> {
type Flags = WriteFlagsImpl;
fn get(&self, db: &Self::Database, key: &[u8]) -> Result<&[u8], Self::Error> {
let snapshot = self.snapshots.get(db).ok_or(ErrorImpl::DbIsForeignError)?;
snapshot.get(key).ok_or(ErrorImpl::KeyValuePairNotFound)
let snapshot = self.snapshots.get(db).ok_or_else(|| ErrorImpl::DbIsForeignError)?;
snapshot.get(key).ok_or_else(|| ErrorImpl::KeyValuePairNotFound)
}
#[cfg(not(feature = "db-dup-sort"))]
fn put(
&mut self,
db: &Self::Database,
key: &[u8],
value: &[u8],
_flags: Self::Flags,
) -> Result<(), Self::Error> {
let snapshot = self
.snapshots
.get_mut(db)
.ok_or_else(|| ErrorImpl::DbIsForeignError)?;
fn put(&mut self, db: &Self::Database, key: &[u8], value: &[u8], _flags: Self::Flags) -> Result<(), Self::Error> {
let snapshot = self.snapshots.get_mut(db).ok_or_else(|| ErrorImpl::DbIsForeignError)?;
snapshot.put(key, value);
Ok(())
}
#[cfg(feature = "db-dup-sort")]
fn put(
&mut self,
db: &Self::Database,
key: &[u8],
value: &[u8],
_flags: Self::Flags,
) -> Result<(), Self::Error> {
fn put(&mut self, db: &Self::Database, key: &[u8], value: &[u8], _flags: Self::Flags) -> Result<(), Self::Error> {
use super::DatabaseFlagsImpl;
let snapshot = self
.snapshots
.get_mut(db)
.ok_or(ErrorImpl::DbIsForeignError)?;
let snapshot = self.snapshots.get_mut(db).ok_or_else(|| ErrorImpl::DbIsForeignError)?;
if snapshot.flags().contains(DatabaseFlagsImpl::DUP_SORT) {
snapshot.put_dup(key, value);
} else {
@ -143,40 +118,24 @@ impl<'t> BackendRwTransaction for RwTransactionImpl<'t> {
#[cfg(not(feature = "db-dup-sort"))]
fn del(&mut self, db: &Self::Database, key: &[u8]) -> Result<(), Self::Error> {
let snapshot = self
.snapshots
.get_mut(db)
.ok_or_else(|| ErrorImpl::DbIsForeignError)?;
let snapshot = self.snapshots.get_mut(db).ok_or_else(|| ErrorImpl::DbIsForeignError)?;
let deleted = snapshot.del(key);
Ok(deleted.ok_or_else(|| ErrorImpl::KeyValuePairNotFound)?)
}
#[cfg(feature = "db-dup-sort")]
fn del(
&mut self,
db: &Self::Database,
key: &[u8],
value: Option<&[u8]>,
) -> Result<(), Self::Error> {
fn del(&mut self, db: &Self::Database, key: &[u8], value: Option<&[u8]>) -> Result<(), Self::Error> {
use super::DatabaseFlagsImpl;
let snapshot = self
.snapshots
.get_mut(db)
.ok_or(ErrorImpl::DbIsForeignError)?;
let snapshot = self.snapshots.get_mut(db).ok_or_else(|| ErrorImpl::DbIsForeignError)?;
let deleted = match (value, snapshot.flags()) {
(Some(value), flags) if flags.contains(DatabaseFlagsImpl::DUP_SORT) => {
snapshot.del_exact(key, value)
}
(Some(value), flags) if flags.contains(DatabaseFlagsImpl::DUP_SORT) => snapshot.del_exact(key, value),
_ => snapshot.del(key),
};
deleted.ok_or(ErrorImpl::KeyValuePairNotFound)
Ok(deleted.ok_or_else(|| ErrorImpl::KeyValuePairNotFound)?)
}
fn clear_db(&mut self, db: &Self::Database) -> Result<(), Self::Error> {
let snapshot = self
.snapshots
.get_mut(db)
.ok_or(ErrorImpl::DbIsForeignError)?;
let snapshot = self.snapshots.get_mut(db).ok_or_else(|| ErrorImpl::DbIsForeignError)?;
snapshot.clear();
Ok(())
}
@ -185,7 +144,7 @@ impl<'t> BackendRwTransaction for RwTransactionImpl<'t> {
let mut dbs = self.env.dbs_mut()?;
for (id, snapshot) in self.snapshots {
let db = dbs.arena.get_mut(id.0).ok_or(ErrorImpl::DbIsForeignError)?;
let db = dbs.arena.get_mut(id.0).ok_or_else(|| ErrorImpl::DbIsForeignError)?;
db.replace(snapshot);
}
@ -202,7 +161,7 @@ impl<'t> BackendRwCursorTransaction<'t> for RwTransactionImpl<'t> {
type RoCursor = RoCursorImpl<'t>;
fn open_ro_cursor(&'t self, db: &Self::Database) -> Result<Self::RoCursor, Self::Error> {
let snapshot = self.snapshots.get(db).ok_or(ErrorImpl::DbIsForeignError)?;
let snapshot = self.snapshots.get(db).ok_or_else(|| ErrorImpl::DbIsForeignError)?;
Ok(RoCursorImpl(snapshot))
}
}

View File

@ -9,12 +9,22 @@
// specific language governing permissions and limitations under the License.
use std::{
fmt::{Debug, Display},
path::{Path, PathBuf},
fmt::{
Debug,
Display,
},
path::{
Path,
PathBuf,
},
};
use crate::{
backend::common::{DatabaseFlags, EnvironmentFlags, WriteFlags},
backend::common::{
DatabaseFlags,
EnvironmentFlags,
WriteFlags,
},
error::StoreError,
};
@ -101,11 +111,7 @@ pub trait BackendEnvironment<'e>: Debug {
fn open_db(&self, name: Option<&str>) -> Result<Self::Database, Self::Error>;
fn create_db(
&self,
name: Option<&str>,
flags: Self::Flags,
) -> Result<Self::Database, Self::Error>;
fn create_db(&self, name: Option<&str>, flags: Self::Flags) -> Result<Self::Database, Self::Error>;
fn begin_ro_txn(&'e self) -> Result<Self::RoTransaction, Self::Error>;
@ -142,24 +148,13 @@ pub trait BackendRwTransaction: Debug {
fn get(&self, db: &Self::Database, key: &[u8]) -> Result<&[u8], Self::Error>;
fn put(
&mut self,
db: &Self::Database,
key: &[u8],
value: &[u8],
flags: Self::Flags,
) -> Result<(), Self::Error>;
fn put(&mut self, db: &Self::Database, key: &[u8], value: &[u8], flags: Self::Flags) -> Result<(), Self::Error>;
#[cfg(not(feature = "db-dup-sort"))]
fn del(&mut self, db: &Self::Database, key: &[u8]) -> Result<(), Self::Error>;
#[cfg(feature = "db-dup-sort")]
fn del(
&mut self,
db: &Self::Database,
key: &[u8],
value: Option<&[u8]>,
) -> Result<(), Self::Error>;
fn del(&mut self, db: &Self::Database, key: &[u8], value: Option<&[u8]>) -> Result<(), Self::Error>;
fn clear_db(&mut self, db: &Self::Database) -> Result<(), Self::Error>;

View File

@ -8,9 +8,16 @@
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
use std::{env::args, io, path::Path};
use std::{
env::args,
io,
path::Path,
};
use rkv::migrator::{LmdbArchMigrateError, LmdbArchMigrator};
use rkv::migrator::{
LmdbArchMigrateError,
LmdbArchMigrator,
};
fn main() -> Result<(), LmdbArchMigrateError> {
let mut cli_args = args();
@ -28,8 +35,8 @@ fn main() -> Result<(), LmdbArchMigrateError> {
None => return Err("-s must be followed by database name".into()),
Some(str) => Some(str),
};
}
str => return Err(format!("arg -{str} not recognized").into()),
},
str => return Err(format!("arg -{} not recognized", str).into()),
}
} else {
if env_path.is_some() {

View File

@ -14,11 +14,22 @@
//! the number of key/value pairs to create via the `-n <number>` flag
//! (for which the default value is 50).
use std::{env::args, fs, fs::File, io::Read, path::Path};
use std::{
env::args,
fs,
fs::File,
io::Read,
path::Path,
};
use rkv::{
backend::{BackendEnvironmentBuilder, Lmdb},
Rkv, StoreOptions, Value,
backend::{
BackendEnvironmentBuilder,
Lmdb,
},
Rkv,
StoreOptions,
Value,
};
fn main() {
@ -38,13 +49,13 @@ fn main() {
None => panic!("-s must be followed by database arg"),
Some(str) => Some(str),
};
}
},
"n" => {
num_pairs = match args.next() {
None => panic!("-s must be followed by number of pairs"),
Some(str) => str.parse().expect("number"),
};
}
},
str => panic!("arg -{} not recognized", str),
}
} else {
@ -69,9 +80,7 @@ fn main() {
// of the pairs (assuming maximum key and value sizes).
builder.set_map_size((511 + 65535) * num_pairs * 2);
let rkv = Rkv::from_builder(Path::new(&path), builder).expect("Rkv");
let store = rkv
.open_single(database.as_deref(), StoreOptions::create())
.expect("opened");
let store = rkv.open_single(database.as_deref(), StoreOptions::create()).expect("opened");
let mut writer = rkv.write().expect("writer");
// Generate random values for the number of keys and key/value lengths.
@ -97,9 +106,7 @@ fn main() {
let mut value: Vec<u8> = vec![0; value_len];
random.read_exact(&mut value[0..value_len]).unwrap();
store
.put(&mut writer, key, &Value::Blob(&value))
.expect("wrote");
store.put(&mut writer, key, &Value::Blob(&value)).expect("wrote");
}
writer.commit().expect("committed");

View File

@ -11,19 +11,38 @@
use std::{
fs,
os::raw::c_uint,
path::{Path, PathBuf},
path::{
Path,
PathBuf,
},
};
#[cfg(any(feature = "db-dup-sort", feature = "db-int-key"))]
use crate::backend::{BackendDatabaseFlags, DatabaseFlags};
use crate::backend::{
BackendDatabaseFlags,
DatabaseFlags,
};
use crate::{
backend::{
BackendEnvironment, BackendEnvironmentBuilder, BackendRoCursorTransaction,
BackendRwCursorTransaction, SafeModeError,
BackendEnvironment,
BackendEnvironmentBuilder,
BackendRoCursorTransaction,
BackendRwCursorTransaction,
SafeModeError,
},
error::{
CloseError,
StoreError,
},
readwrite::{
Reader,
Writer,
},
store::{
single::SingleStore,
CloseOptions,
Options as StoreOptions,
},
error::{CloseError, StoreError},
readwrite::{Reader, Writer},
store::{single::SingleStore, CloseOptions, Options as StoreOptions},
};
#[cfg(feature = "db-dup-sort")]
@ -42,7 +61,7 @@ pub static DEFAULT_MAX_DBS: c_uint = 5;
/// Wrapper around an `Environment` (e.g. such as an `LMDB` or `SafeMode` environment).
#[derive(Debug)]
pub struct Rkv<E> {
_path: PathBuf,
path: PathBuf,
env: E,
}
@ -85,7 +104,7 @@ where
B: BackendEnvironmentBuilder<'e, Environment = E>,
{
Ok(Rkv {
_path: path.into(),
path: path.into(),
env: builder.open(path).map_err(|e| e.into())?,
})
}
@ -171,28 +190,20 @@ where
T: Into<Option<&'s str>>,
{
if opts.create {
self.env
.create_db(name.into(), opts.flags)
.map_err(|e| match e.into() {
#[cfg(feature = "lmdb")]
StoreError::LmdbError(lmdb::Error::BadRslot) => {
StoreError::open_during_transaction()
}
StoreError::SafeModeError(SafeModeError::DbsIllegalOpen) => {
StoreError::open_during_transaction()
}
self.env.create_db(name.into(), opts.flags).map_err(|e| {
match e.into() {
StoreError::LmdbError(lmdb::Error::BadRslot) => StoreError::open_during_transaction(),
StoreError::SafeModeError(SafeModeError::DbsIllegalOpen) => StoreError::open_during_transaction(),
e => e,
})
}
})
} else {
self.env.open_db(name.into()).map_err(|e| match e.into() {
#[cfg(feature = "lmdb")]
StoreError::LmdbError(lmdb::Error::BadRslot) => {
StoreError::open_during_transaction()
self.env.open_db(name.into()).map_err(|e| {
match e.into() {
StoreError::LmdbError(lmdb::Error::BadRslot) => StoreError::open_during_transaction(),
StoreError::SafeModeError(SafeModeError::DbsIllegalOpen) => StoreError::open_during_transaction(),
e => e,
}
StoreError::SafeModeError(SafeModeError::DbsIllegalOpen) => {
StoreError::open_during_transaction()
}
e => e,
})
}
}

View File

@ -8,7 +8,13 @@
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
use std::{io, path::PathBuf, sync, thread, thread::ThreadId};
use std::{
io,
path::PathBuf,
sync,
thread,
thread::ThreadId,
};
use thiserror::Error;
@ -21,7 +27,10 @@ pub enum DataError {
UnknownType(u8),
#[error("unexpected type tag: expected {expected}, got {actual}")]
UnexpectedType { expected: Type, actual: Type },
UnexpectedType {
expected: Type,
actual: Type,
},
#[error("empty data; expected tag")]
Empty,
@ -74,7 +83,6 @@ pub enum StoreError {
#[error("data error: {0:?}")]
DataError(#[from] DataError),
#[cfg(feature = "lmdb")]
#[error("lmdb backend error: {0}")]
LmdbError(lmdb::Error),

View File

@ -10,12 +10,18 @@
use std::{
io,
path::{Path, PathBuf},
path::{
Path,
PathBuf,
},
};
use url::Url;
use crate::{error::StoreError, value::Value};
use crate::{
error::StoreError,
value::Value,
};
pub(crate) fn read_transform(value: Result<&[u8], StoreError>) -> Result<Value, StoreError> {
match value {
@ -34,9 +40,7 @@ where
Ok(if cfg!(target_os = "windows") {
let map_err = |_| io::Error::new(io::ErrorKind::Other, "path canonicalization error");
Url::from_file_path(&canonical)
.and_then(|url| url.to_file_path())
.map_err(map_err)?
Url::from_file_path(&canonical).and_then(|url| url.to_file_path()).map_err(map_err)?
} else {
canonical
})

View File

@ -7,7 +7,6 @@
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
#![allow(clippy::from_over_into)] // TODO: `Into` implementations in [safe/lmdb]/flags.rs
//! A simple, humane, typed key-value storage solution. It supports multiple backend
//! engines with varying guarantees, such as [LMDB](http://www.lmdb.tech/doc/) for
@ -46,7 +45,7 @@
//! ## Basic Usage
//! ```
//! use rkv::{Manager, Rkv, SingleStore, Value, StoreOptions};
//! use rkv::backend::{SafeMode, SafeModeEnvironment};
//! use rkv::backend::{Lmdb, LmdbEnvironment};
//! use std::fs;
//! use tempfile::Builder;
//!
@ -65,8 +64,8 @@
//! // The `Manager` enforces that each process opens the same environment at most once by
//! // caching a handle to each environment that it opens. Use it to retrieve the handle
//! // to an opened environment—or create one if it hasn't already been opened:
//! let mut manager = Manager::<SafeModeEnvironment>::singleton().write().unwrap();
//! let created_arc = manager.get_or_create(path, Rkv::new::<SafeMode>).unwrap();
//! let mut manager = Manager::<LmdbEnvironment>::singleton().write().unwrap();
//! let created_arc = manager.get_or_create(path, Rkv::new::<Lmdb>).unwrap();
//! let env = created_arc.read().unwrap();
//!
//! // Then you can use the environment handle to get a handle to a datastore:
@ -209,20 +208,38 @@ mod manager;
mod readwrite;
pub mod backend;
#[cfg(feature = "lmdb")]
pub mod migrator;
pub mod store;
pub mod value;
pub use backend::{DatabaseFlags, EnvironmentFlags, WriteFlags};
pub use backend::{
DatabaseFlags,
EnvironmentFlags,
WriteFlags,
};
pub use env::Rkv;
pub use error::{DataError, MigrateError, StoreError};
pub use error::{
DataError,
MigrateError,
StoreError,
};
pub use manager::Manager;
#[cfg(feature = "lmdb")]
pub use migrator::Migrator;
pub use readwrite::{Readable, Reader, Writer};
pub use store::{keys::EncodableKey, single::SingleStore, CloseOptions, Options as StoreOptions};
pub use value::{OwnedValue, Value};
pub use readwrite::{
Readable,
Reader,
Writer,
};
pub use store::{
keys::EncodableKey,
single::SingleStore,
CloseOptions,
Options as StoreOptions,
};
pub use value::{
OwnedValue,
Value,
};
#[cfg(feature = "db-dup-sort")]
pub use store::multi::MultiStore;

View File

@ -9,20 +9,35 @@
// specific language governing permissions and limitations under the License.
use std::{
collections::{btree_map::Entry, BTreeMap},
collections::{
btree_map::Entry,
BTreeMap,
},
os::raw::c_uint,
path::{Path, PathBuf},
path::{
Path,
PathBuf,
},
result,
sync::{Arc, RwLock},
sync::{
Arc,
RwLock,
},
};
use lazy_static::lazy_static;
#[cfg(feature = "lmdb")]
use crate::backend::LmdbEnvironment;
use crate::{
backend::{BackendEnvironment, BackendEnvironmentBuilder, SafeModeEnvironment},
error::{CloseError, StoreError},
backend::{
BackendEnvironment,
BackendEnvironmentBuilder,
LmdbEnvironment,
SafeModeEnvironment,
},
error::{
CloseError,
StoreError,
},
helpers::canonicalize_path,
store::CloseOptions,
Rkv,
@ -32,14 +47,9 @@ type Result<T> = result::Result<T, StoreError>;
type CloseResult<T> = result::Result<T, CloseError>;
type SharedRkv<E> = Arc<RwLock<Rkv<E>>>;
#[cfg(feature = "lmdb")]
lazy_static! {
static ref MANAGER_LMDB: RwLock<Manager<LmdbEnvironment>> = RwLock::new(Manager::new());
}
lazy_static! {
static ref MANAGER_SAFE_MODE: RwLock<Manager<SafeModeEnvironment>> =
RwLock::new(Manager::new());
static ref MANAGER_SAFE_MODE: RwLock<Manager<SafeModeEnvironment>> = RwLock::new(Manager::new());
}
/// A process is only permitted to have one open handle to each Rkv environment. This
@ -96,17 +106,12 @@ where
Entry::Vacant(e) => {
let k = Arc::new(RwLock::new(f(e.key().as_path())?));
e.insert(k).clone()
}
},
})
}
/// Return the open env at `path` with `capacity`, or create it by calling `f`.
pub fn get_or_create_with_capacity<'p, F, P>(
&mut self,
path: P,
capacity: c_uint,
f: F,
) -> Result<SharedRkv<E>>
pub fn get_or_create_with_capacity<'p, F, P>(&mut self, path: P, capacity: c_uint, f: F) -> Result<SharedRkv<E>>
where
F: FnOnce(&Path, c_uint) -> Result<Rkv<E>>,
P: Into<&'p Path>,
@ -121,17 +126,12 @@ where
Entry::Vacant(e) => {
let k = Arc::new(RwLock::new(f(e.key().as_path(), capacity)?));
e.insert(k).clone()
}
},
})
}
/// Return a new Rkv environment from the builder, or create it by calling `f`.
pub fn get_or_create_from_builder<'p, F, P, B>(
&mut self,
path: P,
builder: B,
f: F,
) -> Result<SharedRkv<E>>
pub fn get_or_create_from_builder<'p, F, P, B>(&mut self, path: P, builder: B, f: F) -> Result<SharedRkv<E>>
where
F: FnOnce(&Path, B) -> Result<Rkv<E>>,
P: Into<&'p Path>,
@ -147,7 +147,7 @@ where
Entry::Vacant(e) => {
let k = Arc::new(RwLock::new(f(e.key().as_path(), builder)?));
e.insert(k).clone()
}
},
})
}
@ -164,29 +164,25 @@ where
};
match self.environments.entry(canonical) {
Entry::Vacant(_) => Ok(()),
Entry::Occupied(e) if Arc::strong_count(e.get()) > 1 => {
Err(CloseError::EnvironmentStillOpen)
}
Entry::Occupied(e) if Arc::strong_count(e.get()) > 1 => Err(CloseError::EnvironmentStillOpen),
Entry::Occupied(e) => {
let env = Arc::try_unwrap(e.remove())
.map_err(|_| CloseError::UnknownEnvironmentStillOpen)?;
let env = Arc::try_unwrap(e.remove()).map_err(|_| CloseError::UnknownEnvironmentStillOpen)?;
env.into_inner()?.close(options)?;
Ok(())
}
},
}
}
}
#[cfg(feature = "lmdb")]
impl Manager<LmdbEnvironment> {
pub fn singleton() -> &'static RwLock<Manager<LmdbEnvironment>> {
&MANAGER_LMDB
&*MANAGER_LMDB
}
}
impl Manager<SafeModeEnvironment> {
pub fn singleton() -> &'static RwLock<Manager<SafeModeEnvironment>> {
&MANAGER_SAFE_MODE
&*MANAGER_SAFE_MODE
}
}
@ -199,31 +195,21 @@ mod tests {
use tempfile::Builder;
#[cfg(feature = "lmdb")]
use backend::Lmdb;
/// Test that one can mutate managed Rkv instances in surprising ways.
#[cfg(feature = "lmdb")]
#[test]
fn test_mutate_managed_rkv() {
let mut manager = Manager::<LmdbEnvironment>::new();
let root1 = Builder::new()
.prefix("test_mutate_managed_rkv_1")
.tempdir()
.expect("tempdir");
let root1 = Builder::new().prefix("test_mutate_managed_rkv_1").tempdir().expect("tempdir");
fs::create_dir_all(root1.path()).expect("dir created");
let path1 = root1.path();
let arc = manager
.get_or_create(path1, Rkv::new::<Lmdb>)
.expect("created");
let arc = manager.get_or_create(path1, Rkv::new::<Lmdb>).expect("created");
// Arc<RwLock<>> has interior mutability, so we can replace arc's Rkv instance with a new
// instance that has a different path.
let root2 = Builder::new()
.prefix("test_mutate_managed_rkv_2")
.tempdir()
.expect("tempdir");
let root2 = Builder::new().prefix("test_mutate_managed_rkv_2").tempdir().expect("tempdir");
fs::create_dir_all(root2.path()).expect("dir created");
let path2 = root2.path();
{
@ -239,9 +225,7 @@ mod tests {
// Meanwhile, a new Arc for path2 has a different pointer, even though its Rkv's path is
// the same as arc's current path.
let path2_arc = manager
.get_or_create(path2, Rkv::new::<Lmdb>)
.expect("success");
let path2_arc = manager.get_or_create(path2, Rkv::new::<Lmdb>).expect("success");
assert!(!Arc::ptr_eq(&path2_arc, &arc));
}
}

View File

@ -44,12 +44,20 @@
//! it cannot overwrite nor append data.
use crate::{
backend::{LmdbEnvironment, SafeModeEnvironment},
backend::{
LmdbEnvironment,
SafeModeEnvironment,
},
error::MigrateError,
Rkv, StoreOptions,
Rkv,
StoreOptions,
};
pub use crate::backend::{LmdbArchMigrateError, LmdbArchMigrateResult, LmdbArchMigrator};
pub use crate::backend::{
LmdbArchMigrateError,
LmdbArchMigrateResult,
LmdbArchMigrator,
};
// FIXME: should parametrize this instead.
@ -100,15 +108,17 @@ macro_rules! fn_migrator {
F: FnOnce(crate::backend::$builder) -> crate::backend::$builder,
D: std::ops::Deref<Target = Rkv<$dst_env>>,
{
use crate::{backend::*, CloseOptions};
use crate::{
backend::*,
CloseOptions,
};
let mut manager = crate::Manager::<$src_env>::singleton().write()?;
let mut builder = Rkv::<$src_env>::environment_builder::<$builder>();
builder.set_max_dbs(crate::env::DEFAULT_MAX_DBS);
builder = build(builder);
let src_env =
manager.get_or_create_from_builder(path, builder, Rkv::from_builder::<$builder>)?;
let src_env = manager.get_or_create_from_builder(path, builder, Rkv::from_builder::<$builder>)?;
Migrator::$migrate(src_env.read()?, dst_env)?;
drop(src_env);
@ -133,15 +143,11 @@ macro_rules! fn_migrator {
match Migrator::$migrate(path, |builder| builder, dst_env) {
// Source environment is an invalid file or corrupted database.
Err(crate::MigrateError::StoreError(crate::StoreError::FileInvalid)) => Ok(()),
Err(crate::MigrateError::StoreError(crate::StoreError::DatabaseCorrupted)) => {
Ok(())
}
Err(crate::MigrateError::StoreError(crate::StoreError::DatabaseCorrupted)) => Ok(()),
// Path not accessible.
Err(crate::MigrateError::StoreError(crate::StoreError::IoError(_))) => Ok(()),
// Path accessible but incompatible for configuration.
Err(crate::MigrateError::StoreError(
crate::StoreError::UnsuitableEnvironmentPath(_),
)) => Ok(()),
Err(crate::MigrateError::StoreError(crate::StoreError::UnsuitableEnvironmentPath(_))) => Ok(()),
// Couldn't close source environment and delete files on disk (e.g. other stores still open).
Err(crate::MigrateError::CloseError(_)) => Ok(()),
// Nothing to migrate.

View File

@ -10,8 +10,12 @@
use crate::{
backend::{
BackendDatabase, BackendRoCursor, BackendRoCursorTransaction, BackendRoTransaction,
BackendRwCursorTransaction, BackendRwTransaction,
BackendDatabase,
BackendRoCursor,
BackendRoCursorTransaction,
BackendRoTransaction,
BackendRwCursorTransaction,
BackendRwTransaction,
},
error::StoreError,
helpers::read_transform,
@ -111,20 +115,12 @@ where
self.0.abort();
}
pub(crate) fn put<K>(
&mut self,
db: &T::Database,
k: &K,
v: &Value,
flags: T::Flags,
) -> Result<(), StoreError>
pub(crate) fn put<K>(&mut self, db: &T::Database, k: &K, v: &Value, flags: T::Flags) -> Result<(), StoreError>
where
K: AsRef<[u8]>,
{
// TODO: don't allocate twice.
self.0
.put(db, k.as_ref(), &v.to_bytes()?, flags)
.map_err(|e| e.into())
self.0.put(db, k.as_ref(), &v.to_bytes()?, flags).map_err(|e| e.into())
}
#[cfg(not(feature = "db-dup-sort"))]
@ -136,12 +132,7 @@ where
}
#[cfg(feature = "db-dup-sort")]
pub(crate) fn delete<K>(
&mut self,
db: &T::Database,
k: &K,
v: Option<&[u8]>,
) -> Result<(), StoreError>
pub(crate) fn delete<K>(&mut self, db: &T::Database, k: &K, v: Option<&[u8]>) -> Result<(), StoreError>
where
K: AsRef<[u8]>,
{

View File

@ -47,6 +47,8 @@ pub struct CloseOptions {
impl CloseOptions {
pub fn delete_files_on_disk() -> CloseOptions {
CloseOptions { delete: true }
CloseOptions {
delete: true,
}
}
}

View File

@ -11,11 +11,20 @@
use std::marker::PhantomData;
use crate::{
backend::{BackendDatabase, BackendRwTransaction},
backend::{
BackendDatabase,
BackendRwTransaction,
},
error::StoreError,
readwrite::{Readable, Writer},
readwrite::{
Readable,
Writer,
},
store::{
keys::{Key, PrimitiveInt},
keys::{
Key,
PrimitiveInt,
},
single::SingleStore,
},
value::Value,
@ -81,32 +90,22 @@ mod tests {
#[test]
fn test_integer_keys() {
let root = Builder::new()
.prefix("test_integer_keys")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_integer_keys").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let k = Rkv::new::<backend::Lmdb>(root.path()).expect("new succeeded");
let s = k.open_integer("s", StoreOptions::create()).expect("open");
macro_rules! test_integer_keys {
($type:ty, $key:expr) => {{
let mut writer = k.write().expect("writer");
s.put(&mut writer, $key, &Value::Str("hello!"))
.expect("write");
assert_eq!(
s.get(&writer, $key).expect("read"),
Some(Value::Str("hello!"))
);
s.put(&mut writer, $key, &Value::Str("hello!")).expect("write");
assert_eq!(s.get(&writer, $key).expect("read"), Some(Value::Str("hello!")));
writer.commit().expect("committed");
let reader = k.read().expect("reader");
assert_eq!(
s.get(&reader, $key).expect("read"),
Some(Value::Str("hello!"))
);
assert_eq!(s.get(&reader, $key).expect("read"), Some(Value::Str("hello!")));
}};
}
@ -116,13 +115,10 @@ mod tests {
#[test]
fn test_clear() {
let root = Builder::new()
.prefix("test_integer_clear")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_integer_clear").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let k = Rkv::new::<backend::Lmdb>(root.path()).expect("new succeeded");
let s = k.open_integer("s", StoreOptions::create()).expect("open");
{
@ -150,13 +146,10 @@ mod tests {
#[test]
fn test_dup() {
let root = Builder::new()
.prefix("test_integer_dup")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_integer_dup").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let k = Rkv::new::<backend::Lmdb>(root.path()).expect("new succeeded");
let s = k.open_integer("s", StoreOptions::create()).expect("open");
{
@ -184,13 +177,10 @@ mod tests {
#[test]
fn test_del() {
let root = Builder::new()
.prefix("test_integer_del")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_integer_del").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let k = Rkv::new::<backend::Lmdb>(root.path()).expect("new succeeded");
let s = k.open_integer("s", StoreOptions::create()).expect("open");
{
@ -234,14 +224,11 @@ mod tests {
#[test]
fn test_persist() {
let root = Builder::new()
.prefix("test_integer_persist")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_integer_persist").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
{
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let k = Rkv::new::<backend::Lmdb>(root.path()).expect("new succeeded");
let s = k.open_integer("s", StoreOptions::create()).expect("open");
let mut writer = k.write().expect("writer");
@ -255,7 +242,7 @@ mod tests {
}
{
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let k = Rkv::new::<backend::Lmdb>(root.path()).expect("new succeeded");
let s = k.open_integer("s", StoreOptions::create()).expect("open");
let reader = k.read().expect("reader");
@ -267,13 +254,10 @@ mod tests {
#[test]
fn test_intertwine_read_write() {
let root = Builder::new()
.prefix("test_integer_intertwine_read_write")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_integer_intertwine_read_write").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let k = Rkv::new::<backend::Lmdb>(root.path()).expect("new succeeded");
let s = k.open_integer("s", StoreOptions::create()).expect("open");
{
@ -295,24 +279,12 @@ mod tests {
}
{
s.put(&mut writer, 1, &Value::Str("goodbye!"))
.expect("write");
s.put(&mut writer, 2, &Value::Str("goodbye!"))
.expect("write");
s.put(&mut writer, 3, &Value::Str("goodbye!"))
.expect("write");
assert_eq!(
s.get(&writer, 1).expect("read"),
Some(Value::Str("goodbye!"))
);
assert_eq!(
s.get(&writer, 2).expect("read"),
Some(Value::Str("goodbye!"))
);
assert_eq!(
s.get(&writer, 3).expect("read"),
Some(Value::Str("goodbye!"))
);
s.put(&mut writer, 1, &Value::Str("goodbye!")).expect("write");
s.put(&mut writer, 2, &Value::Str("goodbye!")).expect("write");
s.put(&mut writer, 3, &Value::Str("goodbye!")).expect("write");
assert_eq!(s.get(&writer, 1).expect("read"), Some(Value::Str("goodbye!")));
assert_eq!(s.get(&writer, 2).expect("read"), Some(Value::Str("goodbye!")));
assert_eq!(s.get(&writer, 3).expect("read"), Some(Value::Str("goodbye!")));
writer.commit().expect("committed");
}
@ -326,28 +298,16 @@ mod tests {
let mut writer = k.write().expect("writer");
s.put(&mut writer, 1, &Value::Str("hello!")).expect("write");
assert_eq!(s.get(&writer, 1).expect("read"), Some(Value::Str("hello!")));
assert_eq!(
s.get(&writer, 2).expect("read"),
Some(Value::Str("goodbye!"))
);
assert_eq!(
s.get(&writer, 3).expect("read"),
Some(Value::Str("goodbye!"))
);
assert_eq!(s.get(&writer, 2).expect("read"), Some(Value::Str("goodbye!")));
assert_eq!(s.get(&writer, 3).expect("read"), Some(Value::Str("goodbye!")));
writer.commit().expect("committed");
}
{
let reader = k.write().expect("reader");
assert_eq!(s.get(&reader, 1).expect("read"), Some(Value::Str("hello!")));
assert_eq!(
s.get(&reader, 2).expect("read"),
Some(Value::Str("goodbye!"))
);
assert_eq!(
s.get(&reader, 3).expect("read"),
Some(Value::Str("goodbye!"))
);
assert_eq!(s.get(&reader, 2).expect("read"), Some(Value::Str("goodbye!")));
assert_eq!(s.get(&reader, 3).expect("read"), Some(Value::Str("goodbye!")));
reader.commit().expect("committed");
}
}
@ -364,10 +324,7 @@ mod tests_safe {
#[test]
fn test_integer_keys() {
let root = Builder::new()
.prefix("test_integer_keys")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_integer_keys").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
@ -377,19 +334,12 @@ mod tests_safe {
($type:ty, $key:expr) => {{
let mut writer = k.write().expect("writer");
s.put(&mut writer, $key, &Value::Str("hello!"))
.expect("write");
assert_eq!(
s.get(&writer, $key).expect("read"),
Some(Value::Str("hello!"))
);
s.put(&mut writer, $key, &Value::Str("hello!")).expect("write");
assert_eq!(s.get(&writer, $key).expect("read"), Some(Value::Str("hello!")));
writer.commit().expect("committed");
let reader = k.read().expect("reader");
assert_eq!(
s.get(&reader, $key).expect("read"),
Some(Value::Str("hello!"))
);
assert_eq!(s.get(&reader, $key).expect("read"), Some(Value::Str("hello!")));
}};
}
@ -399,10 +349,7 @@ mod tests_safe {
#[test]
fn test_clear() {
let root = Builder::new()
.prefix("test_integer_clear")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_integer_clear").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
@ -433,10 +380,7 @@ mod tests_safe {
#[test]
fn test_dup() {
let root = Builder::new()
.prefix("test_integer_dup")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_integer_dup").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
@ -467,10 +411,7 @@ mod tests_safe {
#[test]
fn test_del() {
let root = Builder::new()
.prefix("test_integer_del")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_integer_del").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
@ -517,10 +458,7 @@ mod tests_safe {
#[test]
fn test_persist() {
let root = Builder::new()
.prefix("test_integer_persist")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_integer_persist").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
{
@ -550,10 +488,7 @@ mod tests_safe {
#[test]
fn test_intertwine_read_write() {
let root = Builder::new()
.prefix("test_integer_intertwine_read_write")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_integer_intertwine_read_write").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
@ -578,24 +513,12 @@ mod tests_safe {
}
{
s.put(&mut writer, 1, &Value::Str("goodbye!"))
.expect("write");
s.put(&mut writer, 2, &Value::Str("goodbye!"))
.expect("write");
s.put(&mut writer, 3, &Value::Str("goodbye!"))
.expect("write");
assert_eq!(
s.get(&writer, 1).expect("read"),
Some(Value::Str("goodbye!"))
);
assert_eq!(
s.get(&writer, 2).expect("read"),
Some(Value::Str("goodbye!"))
);
assert_eq!(
s.get(&writer, 3).expect("read"),
Some(Value::Str("goodbye!"))
);
s.put(&mut writer, 1, &Value::Str("goodbye!")).expect("write");
s.put(&mut writer, 2, &Value::Str("goodbye!")).expect("write");
s.put(&mut writer, 3, &Value::Str("goodbye!")).expect("write");
assert_eq!(s.get(&writer, 1).expect("read"), Some(Value::Str("goodbye!")));
assert_eq!(s.get(&writer, 2).expect("read"), Some(Value::Str("goodbye!")));
assert_eq!(s.get(&writer, 3).expect("read"), Some(Value::Str("goodbye!")));
writer.commit().expect("committed");
}
@ -609,28 +532,16 @@ mod tests_safe {
let mut writer = k.write().expect("writer");
s.put(&mut writer, 1, &Value::Str("hello!")).expect("write");
assert_eq!(s.get(&writer, 1).expect("read"), Some(Value::Str("hello!")));
assert_eq!(
s.get(&writer, 2).expect("read"),
Some(Value::Str("goodbye!"))
);
assert_eq!(
s.get(&writer, 3).expect("read"),
Some(Value::Str("goodbye!"))
);
assert_eq!(s.get(&writer, 2).expect("read"), Some(Value::Str("goodbye!")));
assert_eq!(s.get(&writer, 3).expect("read"), Some(Value::Str("goodbye!")));
writer.commit().expect("committed");
}
{
let reader = k.write().expect("reader");
assert_eq!(s.get(&reader, 1).expect("read"), Some(Value::Str("hello!")));
assert_eq!(
s.get(&reader, 2).expect("read"),
Some(Value::Str("goodbye!"))
);
assert_eq!(
s.get(&reader, 3).expect("read"),
Some(Value::Str("goodbye!"))
);
assert_eq!(s.get(&reader, 2).expect("read"), Some(Value::Str("goodbye!")));
assert_eq!(s.get(&reader, 3).expect("read"), Some(Value::Str("goodbye!")));
reader.commit().expect("committed");
}
}

View File

@ -11,12 +11,26 @@
use std::marker::PhantomData;
use crate::{
backend::{BackendDatabase, BackendIter, BackendRoCursor, BackendRwTransaction},
backend::{
BackendDatabase,
BackendIter,
BackendRoCursor,
BackendRwTransaction,
},
error::StoreError,
readwrite::{Readable, Writer},
readwrite::{
Readable,
Writer,
},
store::{
keys::{Key, PrimitiveInt},
multi::{Iter, MultiStore},
keys::{
Key,
PrimitiveInt,
},
multi::{
Iter,
MultiStore,
},
},
value::Value,
};
@ -65,13 +79,7 @@ where
self.inner.put(writer, Key::new(&k)?, v)
}
pub fn put_with_flags<T>(
&self,
writer: &mut Writer<T>,
k: K,
v: &Value,
flags: T::Flags,
) -> EmptyResult
pub fn put_with_flags<T>(&self, writer: &mut Writer<T>, k: K, v: &Value, flags: T::Flags) -> EmptyResult
where
T: BackendRwTransaction<Database = D>,
{
@ -111,34 +119,22 @@ mod tests {
#[test]
fn test_integer_keys() {
let root = Builder::new()
.prefix("test_integer_keys")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_integer_keys").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let s = k
.open_multi_integer("s", StoreOptions::create())
.expect("open");
let k = Rkv::new::<backend::Lmdb>(root.path()).expect("new succeeded");
let s = k.open_multi_integer("s", StoreOptions::create()).expect("open");
macro_rules! test_integer_keys {
($type:ty, $key:expr) => {{
let mut writer = k.write().expect("writer");
s.put(&mut writer, $key, &Value::Str("hello!"))
.expect("write");
assert_eq!(
s.get_first(&writer, $key).expect("read"),
Some(Value::Str("hello!"))
);
s.put(&mut writer, $key, &Value::Str("hello!")).expect("write");
assert_eq!(s.get_first(&writer, $key).expect("read"), Some(Value::Str("hello!")));
writer.commit().expect("committed");
let reader = k.read().expect("reader");
assert_eq!(
s.get_first(&reader, $key).expect("read"),
Some(Value::Str("hello!"))
);
assert_eq!(s.get_first(&reader, $key).expect("read"), Some(Value::Str("hello!")));
}};
}
@ -148,31 +144,19 @@ mod tests {
#[test]
fn test_clear() {
let root = Builder::new()
.prefix("test_multi_integer_clear")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_multi_integer_clear").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let s = k
.open_multi_integer("s", StoreOptions::create())
.expect("open");
let k = Rkv::new::<backend::Lmdb>(root.path()).expect("new succeeded");
let s = k.open_multi_integer("s", StoreOptions::create()).expect("open");
{
let mut writer = k.write().expect("writer");
s.put(&mut writer, 1, &Value::Str("hello!")).expect("write");
s.put(&mut writer, 1, &Value::Str("hello1!"))
.expect("write");
s.put(&mut writer, 1, &Value::Str("hello1!")).expect("write");
s.put(&mut writer, 2, &Value::Str("hello!")).expect("write");
assert_eq!(
s.get_first(&writer, 1).expect("read"),
Some(Value::Str("hello!"))
);
assert_eq!(
s.get_first(&writer, 2).expect("read"),
Some(Value::Str("hello!"))
);
assert_eq!(s.get_first(&writer, 1).expect("read"), Some(Value::Str("hello!")));
assert_eq!(s.get_first(&writer, 2).expect("read"), Some(Value::Str("hello!")));
assert_eq!(s.get_first(&writer, 3).expect("read"), None);
writer.commit().expect("committed");
}
@ -191,27 +175,18 @@ mod tests {
#[test]
fn test_dup() {
let root = Builder::new()
.prefix("test_multi_integer_dup")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_multi_integer_dup").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let s = k
.open_multi_integer("s", StoreOptions::create())
.expect("open");
let k = Rkv::new::<backend::Lmdb>(root.path()).expect("new succeeded");
let s = k.open_multi_integer("s", StoreOptions::create()).expect("open");
{
let mut writer = k.write().expect("writer");
s.put(&mut writer, 1, &Value::Str("hello!")).expect("write");
s.put(&mut writer, 1, &Value::Str("hello!")).expect("write");
s.put(&mut writer, 1, &Value::Str("hello1!"))
.expect("write");
assert_eq!(
s.get_first(&writer, 1).expect("read"),
Some(Value::Str("hello!"))
);
s.put(&mut writer, 1, &Value::Str("hello1!")).expect("write");
assert_eq!(s.get_first(&writer, 1).expect("read"), Some(Value::Str("hello!")));
assert_eq!(s.get_first(&writer, 2).expect("read"), None);
assert_eq!(s.get_first(&writer, 3).expect("read"), None);
writer.commit().expect("committed");
@ -231,66 +206,42 @@ mod tests {
#[test]
fn test_dup_2() {
let root = Builder::new()
.prefix("test_multi_integer_dup")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_multi_integer_dup").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let s = k
.open_multi_integer("s", StoreOptions::create())
.expect("open");
let k = Rkv::new::<backend::Lmdb>(root.path()).expect("new succeeded");
let s = k.open_multi_integer("s", StoreOptions::create()).expect("open");
{
let mut writer = k.write().expect("writer");
s.put(&mut writer, 1, &Value::Str("hello!")).expect("write");
s.put(&mut writer, 1, &Value::Str("hello!")).expect("write");
s.put(&mut writer, 1, &Value::Str("hello1!"))
.expect("write");
s.put(&mut writer, 1, &Value::Str("hello1!")).expect("write");
let mut iter = s.get(&writer, 1).expect("read");
assert_eq!(
iter.next().expect("first").expect("ok").1,
Value::Str("hello!")
);
assert_eq!(
iter.next().expect("second").expect("ok").1,
Value::Str("hello1!")
);
assert_eq!(iter.next().expect("first").expect("ok").1, Value::Str("hello!"));
assert_eq!(iter.next().expect("second").expect("ok").1, Value::Str("hello1!"));
assert!(iter.next().is_none());
}
}
#[test]
fn test_del() {
let root = Builder::new()
.prefix("test_multi_integer_dup")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_multi_integer_dup").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let s = k
.open_multi_integer("s", StoreOptions::create())
.expect("open");
let k = Rkv::new::<backend::Lmdb>(root.path()).expect("new succeeded");
let s = k.open_multi_integer("s", StoreOptions::create()).expect("open");
{
let mut writer = k.write().expect("writer");
s.put(&mut writer, 1, &Value::Str("hello!")).expect("write");
s.put(&mut writer, 1, &Value::Str("hello!")).expect("write");
s.put(&mut writer, 1, &Value::Str("hello1!"))
.expect("write");
s.put(&mut writer, 1, &Value::Str("hello1!")).expect("write");
{
let mut iter = s.get(&writer, 1).expect("read");
assert_eq!(
iter.next().expect("first").expect("ok").1,
Value::Str("hello!")
);
assert_eq!(
iter.next().expect("second").expect("ok").1,
Value::Str("hello1!")
);
assert_eq!(iter.next().expect("first").expect("ok").1, Value::Str("hello!"));
assert_eq!(iter.next().expect("second").expect("ok").1, Value::Str("hello1!"));
assert!(iter.next().is_none());
}
writer.commit().expect("committed");
@ -298,38 +249,29 @@ mod tests {
{
let mut writer = k.write().expect("writer");
s.delete(&mut writer, 1, &Value::Str("hello!"))
.expect("deleted");
s.delete(&mut writer, 1, &Value::Str("hello!")).expect("deleted");
writer.commit().expect("committed");
let reader = k.read().expect("reader");
let mut iter = s.get(&reader, 1).expect("read");
assert_eq!(
iter.next().expect("first").expect("ok").1,
Value::Str("hello1!")
);
assert_eq!(iter.next().expect("first").expect("ok").1, Value::Str("hello1!"));
assert!(iter.next().is_none());
}
{
let mut writer = k.write().expect("writer");
s.delete(&mut writer, 1, &Value::Str("hello!"))
.expect_err("deleted");
s.delete(&mut writer, 1, &Value::Str("hello!")).expect_err("deleted");
writer.commit().expect("committed");
let reader = k.read().expect("reader");
let mut iter = s.get(&reader, 1).expect("read");
assert_eq!(
iter.next().expect("first").expect("ok").1,
Value::Str("hello1!")
);
assert_eq!(iter.next().expect("first").expect("ok").1, Value::Str("hello1!"));
assert!(iter.next().is_none());
}
{
let mut writer = k.write().expect("writer");
s.delete(&mut writer, 1, &Value::Str("hello1!"))
.expect("deleted");
s.delete(&mut writer, 1, &Value::Str("hello1!")).expect("deleted");
writer.commit().expect("committed");
let reader = k.read().expect("reader");
@ -339,8 +281,7 @@ mod tests {
{
let mut writer = k.write().expect("writer");
s.delete(&mut writer, 1, &Value::Str("hello1!"))
.expect_err("deleted");
s.delete(&mut writer, 1, &Value::Str("hello1!")).expect_err("deleted");
writer.commit().expect("committed");
let reader = k.read().expect("reader");
@ -351,54 +292,34 @@ mod tests {
#[test]
fn test_persist() {
let root = Builder::new()
.prefix("test_multi_integer_persist")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_multi_integer_persist").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
{
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let s = k
.open_multi_integer("s", StoreOptions::create())
.expect("open");
let k = Rkv::new::<backend::Lmdb>(root.path()).expect("new succeeded");
let s = k.open_multi_integer("s", StoreOptions::create()).expect("open");
let mut writer = k.write().expect("writer");
s.put(&mut writer, 1, &Value::Str("hello!")).expect("write");
s.put(&mut writer, 1, &Value::Str("hello1!"))
.expect("write");
s.put(&mut writer, 1, &Value::Str("hello1!")).expect("write");
s.put(&mut writer, 2, &Value::Str("hello!")).expect("write");
{
let mut iter = s.get(&writer, 1).expect("read");
assert_eq!(
iter.next().expect("first").expect("ok").1,
Value::Str("hello!")
);
assert_eq!(
iter.next().expect("second").expect("ok").1,
Value::Str("hello1!")
);
assert_eq!(iter.next().expect("first").expect("ok").1, Value::Str("hello!"));
assert_eq!(iter.next().expect("second").expect("ok").1, Value::Str("hello1!"));
assert!(iter.next().is_none());
}
writer.commit().expect("committed");
}
{
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let s = k
.open_multi_integer("s", StoreOptions::create())
.expect("open");
let k = Rkv::new::<backend::Lmdb>(root.path()).expect("new succeeded");
let s = k.open_multi_integer("s", StoreOptions::create()).expect("open");
let reader = k.read().expect("reader");
let mut iter = s.get(&reader, 1).expect("read");
assert_eq!(
iter.next().expect("first").expect("ok").1,
Value::Str("hello!")
);
assert_eq!(
iter.next().expect("second").expect("ok").1,
Value::Str("hello1!")
);
assert_eq!(iter.next().expect("first").expect("ok").1, Value::Str("hello!"));
assert_eq!(iter.next().expect("second").expect("ok").1, Value::Str("hello1!"));
assert!(iter.next().is_none());
}
}
@ -415,34 +336,22 @@ mod tests_safe {
#[test]
fn test_integer_keys() {
let root = Builder::new()
.prefix("test_integer_keys")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_integer_keys").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let s = k
.open_multi_integer("s", StoreOptions::create())
.expect("open");
let s = k.open_multi_integer("s", StoreOptions::create()).expect("open");
macro_rules! test_integer_keys {
($type:ty, $key:expr) => {{
let mut writer = k.write().expect("writer");
s.put(&mut writer, $key, &Value::Str("hello!"))
.expect("write");
assert_eq!(
s.get_first(&writer, $key).expect("read"),
Some(Value::Str("hello!"))
);
s.put(&mut writer, $key, &Value::Str("hello!")).expect("write");
assert_eq!(s.get_first(&writer, $key).expect("read"), Some(Value::Str("hello!")));
writer.commit().expect("committed");
let reader = k.read().expect("reader");
assert_eq!(
s.get_first(&reader, $key).expect("read"),
Some(Value::Str("hello!"))
);
assert_eq!(s.get_first(&reader, $key).expect("read"), Some(Value::Str("hello!")));
}};
}
@ -452,31 +361,19 @@ mod tests_safe {
#[test]
fn test_clear() {
let root = Builder::new()
.prefix("test_multi_integer_clear")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_multi_integer_clear").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let s = k
.open_multi_integer("s", StoreOptions::create())
.expect("open");
let s = k.open_multi_integer("s", StoreOptions::create()).expect("open");
{
let mut writer = k.write().expect("writer");
s.put(&mut writer, 1, &Value::Str("hello!")).expect("write");
s.put(&mut writer, 1, &Value::Str("hello1!"))
.expect("write");
s.put(&mut writer, 1, &Value::Str("hello1!")).expect("write");
s.put(&mut writer, 2, &Value::Str("hello!")).expect("write");
assert_eq!(
s.get_first(&writer, 1).expect("read"),
Some(Value::Str("hello!"))
);
assert_eq!(
s.get_first(&writer, 2).expect("read"),
Some(Value::Str("hello!"))
);
assert_eq!(s.get_first(&writer, 1).expect("read"), Some(Value::Str("hello!")));
assert_eq!(s.get_first(&writer, 2).expect("read"), Some(Value::Str("hello!")));
assert_eq!(s.get_first(&writer, 3).expect("read"), None);
writer.commit().expect("committed");
}
@ -495,27 +392,18 @@ mod tests_safe {
#[test]
fn test_dup() {
let root = Builder::new()
.prefix("test_multi_integer_dup")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_multi_integer_dup").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let s = k
.open_multi_integer("s", StoreOptions::create())
.expect("open");
let s = k.open_multi_integer("s", StoreOptions::create()).expect("open");
{
let mut writer = k.write().expect("writer");
s.put(&mut writer, 1, &Value::Str("hello!")).expect("write");
s.put(&mut writer, 1, &Value::Str("hello!")).expect("write");
s.put(&mut writer, 1, &Value::Str("hello1!"))
.expect("write");
assert_eq!(
s.get_first(&writer, 1).expect("read"),
Some(Value::Str("hello!"))
);
s.put(&mut writer, 1, &Value::Str("hello1!")).expect("write");
assert_eq!(s.get_first(&writer, 1).expect("read"), Some(Value::Str("hello!")));
assert_eq!(s.get_first(&writer, 2).expect("read"), None);
assert_eq!(s.get_first(&writer, 3).expect("read"), None);
writer.commit().expect("committed");
@ -535,66 +423,42 @@ mod tests_safe {
#[test]
fn test_dup_2() {
let root = Builder::new()
.prefix("test_multi_integer_dup")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_multi_integer_dup").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let s = k
.open_multi_integer("s", StoreOptions::create())
.expect("open");
let s = k.open_multi_integer("s", StoreOptions::create()).expect("open");
{
let mut writer = k.write().expect("writer");
s.put(&mut writer, 1, &Value::Str("hello!")).expect("write");
s.put(&mut writer, 1, &Value::Str("hello!")).expect("write");
s.put(&mut writer, 1, &Value::Str("hello1!"))
.expect("write");
s.put(&mut writer, 1, &Value::Str("hello1!")).expect("write");
let mut iter = s.get(&writer, 1).expect("read");
assert_eq!(
iter.next().expect("first").expect("ok").1,
Value::Str("hello!")
);
assert_eq!(
iter.next().expect("second").expect("ok").1,
Value::Str("hello1!")
);
assert_eq!(iter.next().expect("first").expect("ok").1, Value::Str("hello!"));
assert_eq!(iter.next().expect("second").expect("ok").1, Value::Str("hello1!"));
assert!(iter.next().is_none());
}
}
#[test]
fn test_del() {
let root = Builder::new()
.prefix("test_multi_integer_dup")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_multi_integer_dup").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let s = k
.open_multi_integer("s", StoreOptions::create())
.expect("open");
let s = k.open_multi_integer("s", StoreOptions::create()).expect("open");
{
let mut writer = k.write().expect("writer");
s.put(&mut writer, 1, &Value::Str("hello!")).expect("write");
s.put(&mut writer, 1, &Value::Str("hello!")).expect("write");
s.put(&mut writer, 1, &Value::Str("hello1!"))
.expect("write");
s.put(&mut writer, 1, &Value::Str("hello1!")).expect("write");
{
let mut iter = s.get(&writer, 1).expect("read");
assert_eq!(
iter.next().expect("first").expect("ok").1,
Value::Str("hello!")
);
assert_eq!(
iter.next().expect("second").expect("ok").1,
Value::Str("hello1!")
);
assert_eq!(iter.next().expect("first").expect("ok").1, Value::Str("hello!"));
assert_eq!(iter.next().expect("second").expect("ok").1, Value::Str("hello1!"));
assert!(iter.next().is_none());
}
writer.commit().expect("committed");
@ -602,38 +466,29 @@ mod tests_safe {
{
let mut writer = k.write().expect("writer");
s.delete(&mut writer, 1, &Value::Str("hello!"))
.expect("deleted");
s.delete(&mut writer, 1, &Value::Str("hello!")).expect("deleted");
writer.commit().expect("committed");
let reader = k.read().expect("reader");
let mut iter = s.get(&reader, 1).expect("read");
assert_eq!(
iter.next().expect("first").expect("ok").1,
Value::Str("hello1!")
);
assert_eq!(iter.next().expect("first").expect("ok").1, Value::Str("hello1!"));
assert!(iter.next().is_none());
}
{
let mut writer = k.write().expect("writer");
s.delete(&mut writer, 1, &Value::Str("hello!"))
.expect_err("deleted");
s.delete(&mut writer, 1, &Value::Str("hello!")).expect_err("deleted");
writer.commit().expect("committed");
let reader = k.read().expect("reader");
let mut iter = s.get(&reader, 1).expect("read");
assert_eq!(
iter.next().expect("first").expect("ok").1,
Value::Str("hello1!")
);
assert_eq!(iter.next().expect("first").expect("ok").1, Value::Str("hello1!"));
assert!(iter.next().is_none());
}
{
let mut writer = k.write().expect("writer");
s.delete(&mut writer, 1, &Value::Str("hello1!"))
.expect("deleted");
s.delete(&mut writer, 1, &Value::Str("hello1!")).expect("deleted");
writer.commit().expect("committed");
let reader = k.read().expect("reader");
@ -643,8 +498,7 @@ mod tests_safe {
{
let mut writer = k.write().expect("writer");
s.delete(&mut writer, 1, &Value::Str("hello1!"))
.expect_err("deleted");
s.delete(&mut writer, 1, &Value::Str("hello1!")).expect_err("deleted");
writer.commit().expect("committed");
let reader = k.read().expect("reader");
@ -655,33 +509,21 @@ mod tests_safe {
#[test]
fn test_persist() {
let root = Builder::new()
.prefix("test_multi_integer_persist")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_multi_integer_persist").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
{
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let s = k
.open_multi_integer("s", StoreOptions::create())
.expect("open");
let s = k.open_multi_integer("s", StoreOptions::create()).expect("open");
let mut writer = k.write().expect("writer");
s.put(&mut writer, 1, &Value::Str("hello!")).expect("write");
s.put(&mut writer, 1, &Value::Str("hello1!"))
.expect("write");
s.put(&mut writer, 1, &Value::Str("hello1!")).expect("write");
s.put(&mut writer, 2, &Value::Str("hello!")).expect("write");
{
let mut iter = s.get(&writer, 1).expect("read");
assert_eq!(
iter.next().expect("first").expect("ok").1,
Value::Str("hello!")
);
assert_eq!(
iter.next().expect("second").expect("ok").1,
Value::Str("hello1!")
);
assert_eq!(iter.next().expect("first").expect("ok").1, Value::Str("hello!"));
assert_eq!(iter.next().expect("second").expect("ok").1, Value::Str("hello1!"));
assert!(iter.next().is_none());
}
writer.commit().expect("committed");
@ -689,20 +531,12 @@ mod tests_safe {
{
let k = Rkv::new::<backend::SafeMode>(root.path()).expect("new succeeded");
let s = k
.open_multi_integer("s", StoreOptions::create())
.expect("open");
let s = k.open_multi_integer("s", StoreOptions::create()).expect("open");
let reader = k.read().expect("reader");
let mut iter = s.get(&reader, 1).expect("read");
assert_eq!(
iter.next().expect("first").expect("ok").1,
Value::Str("hello!")
);
assert_eq!(
iter.next().expect("second").expect("ok").1,
Value::Str("hello1!")
);
assert_eq!(iter.next().expect("first").expect("ok").1, Value::Str("hello!"));
assert_eq!(iter.next().expect("second").expect("ok").1, Value::Str("hello1!"));
assert!(iter.next().is_none());
}
}

View File

@ -11,10 +11,19 @@
use std::marker::PhantomData;
use crate::{
backend::{BackendDatabase, BackendFlags, BackendIter, BackendRoCursor, BackendRwTransaction},
backend::{
BackendDatabase,
BackendFlags,
BackendIter,
BackendRoCursor,
BackendRwTransaction,
},
error::StoreError,
helpers::read_transform,
readwrite::{Readable, Writer},
readwrite::{
Readable,
Writer,
},
value::Value,
};
@ -35,7 +44,9 @@ where
D: BackendDatabase,
{
pub(crate) fn new(db: D) -> MultiStore<D> {
MultiStore { db }
MultiStore {
db,
}
}
/// Provides a cursor to all of the values for the duplicate entries that match this
@ -76,13 +87,7 @@ where
writer.put(&self.db, &k, v, T::Flags::empty())
}
pub fn put_with_flags<T, K>(
&self,
writer: &mut Writer<T>,
k: K,
v: &Value,
flags: T::Flags,
) -> EmptyResult
pub fn put_with_flags<T, K>(&self, writer: &mut Writer<T>, k: K, v: &Value, flags: T::Flags) -> EmptyResult
where
T: BackendRwTransaction<Database = D>,
K: AsRef<[u8]>,
@ -123,9 +128,11 @@ where
fn next(&mut self) -> Option<Self::Item> {
match self.iter.next() {
None => None,
Some(Ok((key, bytes))) => match read_transform(Ok(bytes)) {
Ok(val) => Some(Ok((key, val))),
Err(err) => Some(Err(err)),
Some(Ok((key, bytes))) => {
match read_transform(Ok(bytes)) {
Ok(val) => Some(Ok((key, val))),
Err(err) => Some(Err(err)),
}
},
Some(Err(err)) => Some(Err(err.into())),
}

View File

@ -11,10 +11,19 @@
use std::marker::PhantomData;
use crate::{
backend::{BackendDatabase, BackendFlags, BackendIter, BackendRoCursor, BackendRwTransaction},
backend::{
BackendDatabase,
BackendFlags,
BackendIter,
BackendRoCursor,
BackendRwTransaction,
},
error::StoreError,
helpers::read_transform,
readwrite::{Readable, Writer},
readwrite::{
Readable,
Writer,
},
value::Value,
};
@ -35,7 +44,9 @@ where
D: BackendDatabase,
{
pub(crate) fn new(db: D) -> SingleStore<D> {
SingleStore { db }
SingleStore {
db,
}
}
pub fn get<'r, R, K>(&self, reader: &'r R, k: K) -> Result<Option<Value<'r>>, StoreError>
@ -122,9 +133,11 @@ where
fn next(&mut self) -> Option<Self::Item> {
match self.iter.next() {
None => None,
Some(Ok((key, bytes))) => match read_transform(Ok(bytes)) {
Ok(val) => Some(Ok((key, val))),
Err(err) => Some(Err(err)),
Some(Ok((key, bytes))) => {
match read_transform(Ok(bytes)) {
Ok(val) => Some(Ok((key, val))),
Err(err) => Some(Err(err)),
}
},
Some(Err(err)) => Some(Err(err.into())),
}

View File

@ -11,9 +11,16 @@
use std::fmt;
use arrayref::array_ref;
use bincode::{deserialize, serialize, serialized_size};
use bincode::{
deserialize,
serialize,
serialized_size,
};
use ordered_float::OrderedFloat;
use uuid::{Bytes, Uuid};
use uuid::{
Bytes,
Uuid,
};
use crate::error::DataError;
@ -37,7 +44,6 @@ pub enum Type {
/// We use manual tagging, because <https://github.com/serde-rs/serde/issues/610>.
impl Type {
pub fn from_tag(tag: u8) -> Result<Type, DataError> {
#![allow(clippy::unnecessary_lazy_evaluations)]
Type::from_primitive(tag).ok_or_else(|| DataError::UnknownType(tag))
}
@ -122,9 +128,11 @@ impl<'v> Value<'v> {
fn from_type_and_data(t: Type, data: &'v [u8]) -> Result<Value<'v>, DataError> {
if t == Type::Uuid {
return deserialize(data)
.map_err(|e| DataError::DecodingError {
value_type: t,
err: e,
.map_err(|e| {
DataError::DecodingError {
value_type: t,
err: e,
}
})
.map(uuid)?;
}
@ -141,11 +149,13 @@ impl<'v> Value<'v> {
Type::Uuid => {
// Processed above to avoid verbose duplication of error transforms.
unreachable!()
}
},
}
.map_err(|e| DataError::DecodingError {
value_type: t,
err: e,
.map_err(|e| {
DataError::DecodingError {
value_type: t,
err: e,
}
})
}
@ -230,14 +240,8 @@ mod tests {
assert_eq!(Value::I64(-1000).serialized_size().unwrap(), 9);
assert_eq!(Value::U64(1000u64).serialized_size().unwrap(), 9);
assert_eq!(Value::Bool(true).serialized_size().unwrap(), 2);
assert_eq!(
Value::Instant(1_558_020_865_224).serialized_size().unwrap(),
9
);
assert_eq!(
Value::F64(OrderedFloat(10000.1)).serialized_size().unwrap(),
9
);
assert_eq!(Value::Instant(1_558_020_865_224).serialized_size().unwrap(), 9);
assert_eq!(Value::F64(OrderedFloat(10000.1)).serialized_size().unwrap(), 9);
assert_eq!(Value::Str("hello!").serialized_size().unwrap(), 15);
assert_eq!(Value::Str("¡Hola").serialized_size().unwrap(), 15);
assert_eq!(Value::Blob(b"hello!").serialized_size().unwrap(), 15);

View File

@ -13,16 +13,18 @@ use std::fs;
use tempfile::Builder;
use rkv::{
backend::{Lmdb, SafeMode},
Rkv, StoreOptions, Value,
backend::{
Lmdb,
SafeMode,
},
Rkv,
StoreOptions,
Value,
};
#[test]
fn test_open_safe_same_dir_as_lmdb() {
let root = Builder::new()
.prefix("test_open_safe_same_dir_as_lmdb")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_open_safe_same_dir_as_lmdb").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
// Create database of type A and save to disk.
@ -31,75 +33,39 @@ fn test_open_safe_same_dir_as_lmdb() {
let sk = k.open_single("sk", StoreOptions::create()).expect("opened");
let mut writer = k.write().expect("writer");
sk.put(&mut writer, "foo", &Value::I64(1234))
.expect("wrote");
sk.put(&mut writer, "bar", &Value::Bool(true))
.expect("wrote");
sk.put(&mut writer, "baz", &Value::Str("héllo, yöu"))
.expect("wrote");
assert_eq!(
sk.get(&writer, "foo").expect("read"),
Some(Value::I64(1234))
);
assert_eq!(
sk.get(&writer, "bar").expect("read"),
Some(Value::Bool(true))
);
assert_eq!(
sk.get(&writer, "baz").expect("read"),
Some(Value::Str("héllo, yöu"))
);
sk.put(&mut writer, "foo", &Value::I64(1234)).expect("wrote");
sk.put(&mut writer, "bar", &Value::Bool(true)).expect("wrote");
sk.put(&mut writer, "baz", &Value::Str("héllo, yöu")).expect("wrote");
assert_eq!(sk.get(&writer, "foo").expect("read"), Some(Value::I64(1234)));
assert_eq!(sk.get(&writer, "bar").expect("read"), Some(Value::Bool(true)));
assert_eq!(sk.get(&writer, "baz").expect("read"), Some(Value::Str("héllo, yöu")));
writer.commit().expect("committed");
k.sync(true).expect("synced");
}
// Verify that database of type A was written to disk.
{
let k = Rkv::new::<Lmdb>(root.path()).expect("new succeeded");
let sk = k
.open_single("sk", StoreOptions::default())
.expect("opened");
let sk = k.open_single("sk", StoreOptions::default()).expect("opened");
let reader = k.read().expect("reader");
assert_eq!(
sk.get(&reader, "foo").expect("read"),
Some(Value::I64(1234))
);
assert_eq!(
sk.get(&reader, "bar").expect("read"),
Some(Value::Bool(true))
);
assert_eq!(
sk.get(&reader, "baz").expect("read"),
Some(Value::Str("héllo, yöu"))
);
assert_eq!(sk.get(&reader, "foo").expect("read"), Some(Value::I64(1234)));
assert_eq!(sk.get(&reader, "bar").expect("read"), Some(Value::Bool(true)));
assert_eq!(sk.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")));
}
// Create database of type B and verify that it is empty.
{
let k = Rkv::new::<SafeMode>(root.path()).expect("new succeeded");
let _ = k
.open_single("sk", StoreOptions::default())
.expect_err("not opened");
let _ = k.open_single("sk", StoreOptions::default()).expect_err("not opened");
}
// Verify that database of type A wasn't changed.
{
let k = Rkv::new::<Lmdb>(root.path()).expect("new succeeded");
let sk = k
.open_single("sk", StoreOptions::default())
.expect("opened");
let sk = k.open_single("sk", StoreOptions::default()).expect("opened");
let reader = k.read().expect("reader");
assert_eq!(
sk.get(&reader, "foo").expect("read"),
Some(Value::I64(1234))
);
assert_eq!(
sk.get(&reader, "bar").expect("read"),
Some(Value::Bool(true))
);
assert_eq!(
sk.get(&reader, "baz").expect("read"),
Some(Value::Str("héllo, yöu"))
);
assert_eq!(sk.get(&reader, "foo").expect("read"), Some(Value::I64(1234)));
assert_eq!(sk.get(&reader, "bar").expect("read"), Some(Value::Bool(true)));
assert_eq!(sk.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")));
}
// Create database of type B and save to disk (type A exists at the same path).
{
@ -107,77 +73,40 @@ fn test_open_safe_same_dir_as_lmdb() {
let sk = k.open_single("sk", StoreOptions::create()).expect("opened");
let mut writer = k.write().expect("writer");
sk.put(&mut writer, "foo1", &Value::I64(5678))
.expect("wrote");
sk.put(&mut writer, "bar1", &Value::Bool(false))
.expect("wrote");
sk.put(&mut writer, "baz1", &Value::Str("héllo~ yöu"))
.expect("wrote");
assert_eq!(
sk.get(&writer, "foo1").expect("read"),
Some(Value::I64(5678))
);
assert_eq!(
sk.get(&writer, "bar1").expect("read"),
Some(Value::Bool(false))
);
assert_eq!(
sk.get(&writer, "baz1").expect("read"),
Some(Value::Str("héllo~ yöu"))
);
sk.put(&mut writer, "foo1", &Value::I64(5678)).expect("wrote");
sk.put(&mut writer, "bar1", &Value::Bool(false)).expect("wrote");
sk.put(&mut writer, "baz1", &Value::Str("héllo~ yöu")).expect("wrote");
assert_eq!(sk.get(&writer, "foo1").expect("read"), Some(Value::I64(5678)));
assert_eq!(sk.get(&writer, "bar1").expect("read"), Some(Value::Bool(false)));
assert_eq!(sk.get(&writer, "baz1").expect("read"), Some(Value::Str("héllo~ yöu")));
writer.commit().expect("committed");
k.sync(true).expect("synced");
}
// Verify that database of type B was written to disk.
{
let k = Rkv::new::<SafeMode>(root.path()).expect("new succeeded");
let sk = k
.open_single("sk", StoreOptions::default())
.expect("opened");
let sk = k.open_single("sk", StoreOptions::default()).expect("opened");
let reader = k.read().expect("reader");
assert_eq!(
sk.get(&reader, "foo1").expect("read"),
Some(Value::I64(5678))
);
assert_eq!(
sk.get(&reader, "bar1").expect("read"),
Some(Value::Bool(false))
);
assert_eq!(
sk.get(&reader, "baz1").expect("read"),
Some(Value::Str("héllo~ yöu"))
);
assert_eq!(sk.get(&reader, "foo1").expect("read"), Some(Value::I64(5678)));
assert_eq!(sk.get(&reader, "bar1").expect("read"), Some(Value::Bool(false)));
assert_eq!(sk.get(&reader, "baz1").expect("read"), Some(Value::Str("héllo~ yöu")));
}
// Verify that database of type A still wasn't changed.
{
let k = Rkv::new::<Lmdb>(root.path()).expect("new succeeded");
let sk = k
.open_single("sk", StoreOptions::default())
.expect("opened");
let sk = k.open_single("sk", StoreOptions::default()).expect("opened");
let reader = k.read().expect("reader");
assert_eq!(
sk.get(&reader, "foo").expect("read"),
Some(Value::I64(1234))
);
assert_eq!(
sk.get(&reader, "bar").expect("read"),
Some(Value::Bool(true))
);
assert_eq!(
sk.get(&reader, "baz").expect("read"),
Some(Value::Str("héllo, yöu"))
);
assert_eq!(sk.get(&reader, "foo").expect("read"), Some(Value::I64(1234)));
assert_eq!(sk.get(&reader, "bar").expect("read"), Some(Value::Bool(true)));
assert_eq!(sk.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")));
}
}
#[test]
fn test_open_lmdb_same_dir_as_safe() {
let root = Builder::new()
.prefix("test_open_lmdb_same_dir_as_safe")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_open_lmdb_same_dir_as_safe").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
// Create database of type A and save to disk.
@ -186,75 +115,39 @@ fn test_open_lmdb_same_dir_as_safe() {
let sk = k.open_single("sk", StoreOptions::create()).expect("opened");
let mut writer = k.write().expect("writer");
sk.put(&mut writer, "foo", &Value::I64(1234))
.expect("wrote");
sk.put(&mut writer, "bar", &Value::Bool(true))
.expect("wrote");
sk.put(&mut writer, "baz", &Value::Str("héllo, yöu"))
.expect("wrote");
assert_eq!(
sk.get(&writer, "foo").expect("read"),
Some(Value::I64(1234))
);
assert_eq!(
sk.get(&writer, "bar").expect("read"),
Some(Value::Bool(true))
);
assert_eq!(
sk.get(&writer, "baz").expect("read"),
Some(Value::Str("héllo, yöu"))
);
sk.put(&mut writer, "foo", &Value::I64(1234)).expect("wrote");
sk.put(&mut writer, "bar", &Value::Bool(true)).expect("wrote");
sk.put(&mut writer, "baz", &Value::Str("héllo, yöu")).expect("wrote");
assert_eq!(sk.get(&writer, "foo").expect("read"), Some(Value::I64(1234)));
assert_eq!(sk.get(&writer, "bar").expect("read"), Some(Value::Bool(true)));
assert_eq!(sk.get(&writer, "baz").expect("read"), Some(Value::Str("héllo, yöu")));
writer.commit().expect("committed");
k.sync(true).expect("synced");
}
// Verify that database of type A was written to disk.
{
let k = Rkv::new::<SafeMode>(root.path()).expect("new succeeded");
let sk = k
.open_single("sk", StoreOptions::default())
.expect("opened");
let sk = k.open_single("sk", StoreOptions::default()).expect("opened");
let reader = k.read().expect("reader");
assert_eq!(
sk.get(&reader, "foo").expect("read"),
Some(Value::I64(1234))
);
assert_eq!(
sk.get(&reader, "bar").expect("read"),
Some(Value::Bool(true))
);
assert_eq!(
sk.get(&reader, "baz").expect("read"),
Some(Value::Str("héllo, yöu"))
);
assert_eq!(sk.get(&reader, "foo").expect("read"), Some(Value::I64(1234)));
assert_eq!(sk.get(&reader, "bar").expect("read"), Some(Value::Bool(true)));
assert_eq!(sk.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")));
}
// Create database of type B and verify that it is empty.
{
let k = Rkv::new::<Lmdb>(root.path()).expect("new succeeded");
let _ = k
.open_single("sk", StoreOptions::default())
.expect_err("not opened");
let _ = k.open_single("sk", StoreOptions::default()).expect_err("not opened");
}
// Verify that database of type A wasn't changed.
{
let k = Rkv::new::<SafeMode>(root.path()).expect("new succeeded");
let sk = k
.open_single("sk", StoreOptions::default())
.expect("opened");
let sk = k.open_single("sk", StoreOptions::default()).expect("opened");
let reader = k.read().expect("reader");
assert_eq!(
sk.get(&reader, "foo").expect("read"),
Some(Value::I64(1234))
);
assert_eq!(
sk.get(&reader, "bar").expect("read"),
Some(Value::Bool(true))
);
assert_eq!(
sk.get(&reader, "baz").expect("read"),
Some(Value::Str("héllo, yöu"))
);
assert_eq!(sk.get(&reader, "foo").expect("read"), Some(Value::I64(1234)));
assert_eq!(sk.get(&reader, "bar").expect("read"), Some(Value::Bool(true)));
assert_eq!(sk.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")));
}
// Create database of type B and save to disk (type A exists at the same path).
{
@ -262,67 +155,33 @@ fn test_open_lmdb_same_dir_as_safe() {
let sk = k.open_single("sk", StoreOptions::create()).expect("opened");
let mut writer = k.write().expect("writer");
sk.put(&mut writer, "foo1", &Value::I64(5678))
.expect("wrote");
sk.put(&mut writer, "bar1", &Value::Bool(false))
.expect("wrote");
sk.put(&mut writer, "baz1", &Value::Str("héllo~ yöu"))
.expect("wrote");
assert_eq!(
sk.get(&writer, "foo1").expect("read"),
Some(Value::I64(5678))
);
assert_eq!(
sk.get(&writer, "bar1").expect("read"),
Some(Value::Bool(false))
);
assert_eq!(
sk.get(&writer, "baz1").expect("read"),
Some(Value::Str("héllo~ yöu"))
);
sk.put(&mut writer, "foo1", &Value::I64(5678)).expect("wrote");
sk.put(&mut writer, "bar1", &Value::Bool(false)).expect("wrote");
sk.put(&mut writer, "baz1", &Value::Str("héllo~ yöu")).expect("wrote");
assert_eq!(sk.get(&writer, "foo1").expect("read"), Some(Value::I64(5678)));
assert_eq!(sk.get(&writer, "bar1").expect("read"), Some(Value::Bool(false)));
assert_eq!(sk.get(&writer, "baz1").expect("read"), Some(Value::Str("héllo~ yöu")));
writer.commit().expect("committed");
k.sync(true).expect("synced");
}
// Verify that database of type B was written to disk.
{
let k = Rkv::new::<Lmdb>(root.path()).expect("new succeeded");
let sk = k
.open_single("sk", StoreOptions::default())
.expect("opened");
let sk = k.open_single("sk", StoreOptions::default()).expect("opened");
let reader = k.read().expect("reader");
assert_eq!(
sk.get(&reader, "foo1").expect("read"),
Some(Value::I64(5678))
);
assert_eq!(
sk.get(&reader, "bar1").expect("read"),
Some(Value::Bool(false))
);
assert_eq!(
sk.get(&reader, "baz1").expect("read"),
Some(Value::Str("héllo~ yöu"))
);
assert_eq!(sk.get(&reader, "foo1").expect("read"), Some(Value::I64(5678)));
assert_eq!(sk.get(&reader, "bar1").expect("read"), Some(Value::Bool(false)));
assert_eq!(sk.get(&reader, "baz1").expect("read"), Some(Value::Str("héllo~ yöu")));
}
// Verify that database of type A still wasn't changed.
{
let k = Rkv::new::<SafeMode>(root.path()).expect("new succeeded");
let sk = k
.open_single("sk", StoreOptions::default())
.expect("opened");
let sk = k.open_single("sk", StoreOptions::default()).expect("opened");
let reader = k.read().expect("reader");
assert_eq!(
sk.get(&reader, "foo").expect("read"),
Some(Value::I64(1234))
);
assert_eq!(
sk.get(&reader, "bar").expect("read"),
Some(Value::Bool(true))
);
assert_eq!(
sk.get(&reader, "baz").expect("read"),
Some(Value::Str("héllo, yöu"))
);
assert_eq!(sk.get(&reader, "foo").expect("read"), Some(Value::I64(1234)));
assert_eq!(sk.get(&reader, "bar").expect("read"), Some(Value::Bool(true)));
assert_eq!(sk.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")));
}
}

File diff suppressed because it is too large Load Diff

View File

@ -8,40 +8,41 @@
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
use std::{fs, path::Path};
use std::{
fs,
path::Path,
};
use tempfile::Builder;
use rkv::{
backend::{Lmdb, LmdbEnvironment, SafeMode, SafeModeEnvironment},
Manager, Migrator, Rkv, StoreOptions, Value,
backend::{
Lmdb,
LmdbEnvironment,
SafeMode,
SafeModeEnvironment,
},
Manager,
Migrator,
Rkv,
StoreOptions,
Value,
};
macro_rules! populate_store {
($env:expr) => {
let store = $env
.open_single("store", StoreOptions::create())
.expect("opened");
let store = $env.open_single("store", StoreOptions::create()).expect("opened");
let mut writer = $env.write().expect("writer");
store
.put(&mut writer, "foo", &Value::I64(1234))
.expect("wrote");
store
.put(&mut writer, "bar", &Value::Bool(true))
.expect("wrote");
store
.put(&mut writer, "baz", &Value::Str("héllo, yöu"))
.expect("wrote");
store.put(&mut writer, "foo", &Value::I64(1234)).expect("wrote");
store.put(&mut writer, "bar", &Value::Bool(true)).expect("wrote");
store.put(&mut writer, "baz", &Value::Str("héllo, yöu")).expect("wrote");
writer.commit().expect("committed");
};
}
#[test]
fn test_open_migrator_lmdb_to_safe() {
let root = Builder::new()
.prefix("test_open_migrator_lmdb_to_safe")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_open_migrator_lmdb_to_safe").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
// Populate source environment and persist to disk.
@ -62,48 +63,25 @@ fn test_open_migrator_lmdb_to_safe() {
// Verify that database was written to disk.
{
let src_env = Rkv::new::<Lmdb>(root.path()).expect("new succeeded");
let store = src_env
.open_single("store", StoreOptions::default())
.expect("opened");
let store = src_env.open_single("store", StoreOptions::default()).expect("opened");
let reader = src_env.read().expect("reader");
assert_eq!(
store.get(&reader, "foo").expect("read"),
Some(Value::I64(1234))
);
assert_eq!(
store.get(&reader, "bar").expect("read"),
Some(Value::Bool(true))
);
assert_eq!(
store.get(&reader, "baz").expect("read"),
Some(Value::Str("héllo, yöu"))
);
assert_eq!(store.get(&reader, "foo").expect("read"), Some(Value::I64(1234)));
assert_eq!(store.get(&reader, "bar").expect("read"), Some(Value::Bool(true)));
assert_eq!(store.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")));
}
// Open and migrate.
{
let dst_env = Rkv::new::<SafeMode>(root.path()).expect("new succeeded");
Migrator::open_and_migrate_lmdb_to_safe_mode(root.path(), |builder| builder, &dst_env)
.expect("migrated");
Migrator::open_and_migrate_lmdb_to_safe_mode(root.path(), |builder| builder, &dst_env).expect("migrated");
}
// Verify that the database was indeed migrated.
{
let dst_env = Rkv::new::<SafeMode>(root.path()).expect("new succeeded");
let store = dst_env
.open_single("store", StoreOptions::default())
.expect("opened");
let store = dst_env.open_single("store", StoreOptions::default()).expect("opened");
let reader = dst_env.read().expect("reader");
assert_eq!(
store.get(&reader, "foo").expect("read"),
Some(Value::I64(1234))
);
assert_eq!(
store.get(&reader, "bar").expect("read"),
Some(Value::Bool(true))
);
assert_eq!(
store.get(&reader, "baz").expect("read"),
Some(Value::Str("héllo, yöu"))
);
assert_eq!(store.get(&reader, "foo").expect("read"), Some(Value::I64(1234)));
assert_eq!(store.get(&reader, "bar").expect("read"), Some(Value::Bool(true)));
assert_eq!(store.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")));
}
// Check if the old files were deleted from disk.
{
@ -118,10 +96,7 @@ fn test_open_migrator_lmdb_to_safe() {
#[test]
fn test_open_migrator_safe_to_lmdb() {
let root = Builder::new()
.prefix("test_open_migrator_safe_to_lmdb")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_open_migrator_safe_to_lmdb").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
// Populate source environment and persist to disk.
@ -139,48 +114,25 @@ fn test_open_migrator_safe_to_lmdb() {
// Verify that database was written to disk.
{
let src_env = Rkv::new::<SafeMode>(root.path()).expect("new succeeded");
let store = src_env
.open_single("store", StoreOptions::default())
.expect("opened");
let store = src_env.open_single("store", StoreOptions::default()).expect("opened");
let reader = src_env.read().expect("reader");
assert_eq!(
store.get(&reader, "foo").expect("read"),
Some(Value::I64(1234))
);
assert_eq!(
store.get(&reader, "bar").expect("read"),
Some(Value::Bool(true))
);
assert_eq!(
store.get(&reader, "baz").expect("read"),
Some(Value::Str("héllo, yöu"))
);
assert_eq!(store.get(&reader, "foo").expect("read"), Some(Value::I64(1234)));
assert_eq!(store.get(&reader, "bar").expect("read"), Some(Value::Bool(true)));
assert_eq!(store.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")));
}
// Open and migrate.
{
let dst_env = Rkv::new::<Lmdb>(root.path()).expect("new succeeded");
Migrator::open_and_migrate_safe_mode_to_lmdb(root.path(), |builder| builder, &dst_env)
.expect("migrated");
Migrator::open_and_migrate_safe_mode_to_lmdb(root.path(), |builder| builder, &dst_env).expect("migrated");
}
// Verify that the database was indeed migrated.
{
let dst_env = Rkv::new::<Lmdb>(root.path()).expect("new succeeded");
let store = dst_env
.open_single("store", StoreOptions::default())
.expect("opened");
let store = dst_env.open_single("store", StoreOptions::default()).expect("opened");
let reader = dst_env.read().expect("reader");
assert_eq!(
store.get(&reader, "foo").expect("read"),
Some(Value::I64(1234))
);
assert_eq!(
store.get(&reader, "bar").expect("read"),
Some(Value::Bool(true))
);
assert_eq!(
store.get(&reader, "baz").expect("read"),
Some(Value::Str("héllo, yöu"))
);
assert_eq!(store.get(&reader, "foo").expect("read"), Some(Value::I64(1234)));
assert_eq!(store.get(&reader, "bar").expect("read"), Some(Value::Bool(true)));
assert_eq!(store.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")));
}
// Check if the old files were deleted from disk.
{
@ -192,10 +144,7 @@ fn test_open_migrator_safe_to_lmdb() {
#[test]
fn test_open_migrator_round_trip() {
let root = Builder::new()
.prefix("test_open_migrator_lmdb_to_safe")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_open_migrator_lmdb_to_safe").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
// Populate source environment and persist to disk.
@ -207,34 +156,21 @@ fn test_open_migrator_round_trip() {
// Open and migrate.
{
let dst_env = Rkv::new::<SafeMode>(root.path()).expect("new succeeded");
Migrator::open_and_migrate_lmdb_to_safe_mode(root.path(), |builder| builder, &dst_env)
.expect("migrated");
Migrator::open_and_migrate_lmdb_to_safe_mode(root.path(), |builder| builder, &dst_env).expect("migrated");
}
// Open and migrate back.
{
let dst_env = Rkv::new::<Lmdb>(root.path()).expect("new succeeded");
Migrator::open_and_migrate_safe_mode_to_lmdb(root.path(), |builder| builder, &dst_env)
.expect("migrated");
Migrator::open_and_migrate_safe_mode_to_lmdb(root.path(), |builder| builder, &dst_env).expect("migrated");
}
// Verify that the database was indeed migrated twice.
{
let dst_env = Rkv::new::<Lmdb>(root.path()).expect("new succeeded");
let store = dst_env
.open_single("store", StoreOptions::default())
.expect("opened");
let store = dst_env.open_single("store", StoreOptions::default()).expect("opened");
let reader = dst_env.read().expect("reader");
assert_eq!(
store.get(&reader, "foo").expect("read"),
Some(Value::I64(1234))
);
assert_eq!(
store.get(&reader, "bar").expect("read"),
Some(Value::Bool(true))
);
assert_eq!(
store.get(&reader, "baz").expect("read"),
Some(Value::Str("héllo, yöu"))
);
assert_eq!(store.get(&reader, "foo").expect("read"), Some(Value::I64(1234)));
assert_eq!(store.get(&reader, "bar").expect("read"), Some(Value::Bool(true)));
assert_eq!(store.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")));
}
// Check if the right files are finally present on disk.
{
@ -252,10 +188,7 @@ fn test_open_migrator_round_trip() {
#[test]
fn test_easy_migrator_no_dir_1() {
let root = Builder::new()
.prefix("test_easy_migrator_no_dir")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_easy_migrator_no_dir").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
// This won't fail with IoError even though the path is a bogus path, because this
@ -276,10 +209,7 @@ fn test_easy_migrator_no_dir_1() {
#[test]
fn test_easy_migrator_no_dir_2() {
let root = Builder::new()
.prefix("test_easy_migrator_no_dir")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_easy_migrator_no_dir").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
// This won't fail with IoError even though the path is a bogus path, because this
@ -300,10 +230,7 @@ fn test_easy_migrator_no_dir_2() {
#[test]
fn test_easy_migrator_invalid_1() {
let root = Builder::new()
.prefix("test_easy_migrator_invalid")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_easy_migrator_invalid").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let dbfile = root.path().join("data.mdb");
@ -327,10 +254,7 @@ fn test_easy_migrator_invalid_1() {
#[test]
fn test_easy_migrator_invalid_2() {
let root = Builder::new()
.prefix("test_easy_migrator_invalid")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_easy_migrator_invalid").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let dbfile = root.path().join("data.safe.bin");
@ -355,10 +279,7 @@ fn test_easy_migrator_invalid_2() {
#[test]
#[should_panic(expected = "migrated: SourceEmpty")]
fn test_migrator_lmdb_to_safe_1() {
let root = Builder::new()
.prefix("test_migrate_lmdb_to_safe")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_migrate_lmdb_to_safe").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let src_env = Rkv::new::<Lmdb>(root.path()).expect("new succeeded");
@ -369,10 +290,7 @@ fn test_migrator_lmdb_to_safe_1() {
#[test]
#[should_panic(expected = "migrated: DestinationNotEmpty")]
fn test_migrator_lmdb_to_safe_2() {
let root = Builder::new()
.prefix("test_migrate_lmdb_to_safe")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_migrate_lmdb_to_safe").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let src_env = Rkv::new::<Lmdb>(root.path()).expect("new succeeded");
@ -384,10 +302,7 @@ fn test_migrator_lmdb_to_safe_2() {
#[test]
fn test_migrator_lmdb_to_safe_3() {
let root = Builder::new()
.prefix("test_migrate_lmdb_to_safe")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_migrate_lmdb_to_safe").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let src_env = Rkv::new::<Lmdb>(root.path()).expect("new succeeded");
@ -395,31 +310,17 @@ fn test_migrator_lmdb_to_safe_3() {
let dst_env = Rkv::new::<SafeMode>(root.path()).expect("new succeeded");
Migrator::migrate_lmdb_to_safe_mode(&src_env, &dst_env).expect("migrated");
let store = dst_env
.open_single("store", StoreOptions::default())
.expect("opened");
let store = dst_env.open_single("store", StoreOptions::default()).expect("opened");
let reader = dst_env.read().expect("reader");
assert_eq!(
store.get(&reader, "foo").expect("read"),
Some(Value::I64(1234))
);
assert_eq!(
store.get(&reader, "bar").expect("read"),
Some(Value::Bool(true))
);
assert_eq!(
store.get(&reader, "baz").expect("read"),
Some(Value::Str("héllo, yöu"))
);
assert_eq!(store.get(&reader, "foo").expect("read"), Some(Value::I64(1234)));
assert_eq!(store.get(&reader, "bar").expect("read"), Some(Value::Bool(true)));
assert_eq!(store.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")));
}
#[test]
#[should_panic(expected = "migrated: SourceEmpty")]
fn test_migrator_safe_to_lmdb_1() {
let root = Builder::new()
.prefix("test_migrate_safe_to_lmdb")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_migrate_safe_to_lmdb").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let src_env = Rkv::new::<SafeMode>(root.path()).expect("new succeeded");
@ -430,10 +331,7 @@ fn test_migrator_safe_to_lmdb_1() {
#[test]
#[should_panic(expected = "migrated: DestinationNotEmpty")]
fn test_migrator_safe_to_lmdb_2() {
let root = Builder::new()
.prefix("test_migrate_safe_to_lmdb")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_migrate_safe_to_lmdb").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let src_env = Rkv::new::<SafeMode>(root.path()).expect("new succeeded");
@ -445,10 +343,7 @@ fn test_migrator_safe_to_lmdb_2() {
#[test]
fn test_migrator_safe_to_lmdb_3() {
let root = Builder::new()
.prefix("test_migrate_safe_to_lmdb")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_migrate_safe_to_lmdb").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let src_env = Rkv::new::<SafeMode>(root.path()).expect("new succeeded");
@ -456,30 +351,16 @@ fn test_migrator_safe_to_lmdb_3() {
let dst_env = Rkv::new::<Lmdb>(root.path()).expect("new succeeded");
Migrator::migrate_safe_mode_to_lmdb(&src_env, &dst_env).expect("migrated");
let store = dst_env
.open_single("store", StoreOptions::default())
.expect("opened");
let store = dst_env.open_single("store", StoreOptions::default()).expect("opened");
let reader = dst_env.read().expect("reader");
assert_eq!(
store.get(&reader, "foo").expect("read"),
Some(Value::I64(1234))
);
assert_eq!(
store.get(&reader, "bar").expect("read"),
Some(Value::Bool(true))
);
assert_eq!(
store.get(&reader, "baz").expect("read"),
Some(Value::Str("héllo, yöu"))
);
assert_eq!(store.get(&reader, "foo").expect("read"), Some(Value::I64(1234)));
assert_eq!(store.get(&reader, "bar").expect("read"), Some(Value::Bool(true)));
assert_eq!(store.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")));
}
#[test]
fn test_easy_migrator_failed_migration_1() {
let root = Builder::new()
.prefix("test_easy_migrator_failed_migration_1")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_easy_migrator_failed_migration_1").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let dbfile = root.path().join("data.mdb");
@ -506,10 +387,7 @@ fn test_easy_migrator_failed_migration_1() {
#[test]
fn test_easy_migrator_failed_migration_2() {
let root = Builder::new()
.prefix("test_easy_migrator_failed_migration_2")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_easy_migrator_failed_migration_2").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let dbfile = root.path().join("data.safe.bin");
@ -535,26 +413,19 @@ fn test_easy_migrator_failed_migration_2() {
}
fn test_easy_migrator_from_manager_failed_migration_1() {
let root = Builder::new()
.prefix("test_easy_migrator_from_manager_failed_migration_1")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_easy_migrator_from_manager_failed_migration_1").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
{
let mut src_manager = Manager::<LmdbEnvironment>::singleton().write().unwrap();
let created_src_arc = src_manager
.get_or_create(root.path(), Rkv::new::<Lmdb>)
.unwrap();
let created_src_arc = src_manager.get_or_create(root.path(), Rkv::new::<Lmdb>).unwrap();
let src_env = created_src_arc.read().unwrap();
populate_store!(&src_env);
src_env.sync(true).expect("synced");
}
{
let mut dst_manager = Manager::<SafeModeEnvironment>::singleton().write().unwrap();
let created_dst_arc_1 = dst_manager
.get_or_create(root.path(), Rkv::new::<SafeMode>)
.unwrap();
let created_dst_arc_1 = dst_manager.get_or_create(root.path(), Rkv::new::<SafeMode>).unwrap();
let dst_env_1 = created_dst_arc_1.read().unwrap();
populate_store!(&dst_env_1);
dst_env_1.sync(true).expect("synced");
@ -568,26 +439,19 @@ fn test_easy_migrator_from_manager_failed_migration_1() {
}
fn test_easy_migrator_from_manager_failed_migration_2() {
let root = Builder::new()
.prefix("test_easy_migrator_from_manager_failed_migration_2")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_easy_migrator_from_manager_failed_migration_2").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
{
let mut src_manager = Manager::<SafeModeEnvironment>::singleton().write().unwrap();
let created_src_arc = src_manager
.get_or_create(root.path(), Rkv::new::<SafeMode>)
.unwrap();
let created_src_arc = src_manager.get_or_create(root.path(), Rkv::new::<SafeMode>).unwrap();
let src_env = created_src_arc.read().unwrap();
populate_store!(&src_env);
src_env.sync(true).expect("synced");
}
{
let mut dst_manager = Manager::<LmdbEnvironment>::singleton().write().unwrap();
let created_dst_arc_1 = dst_manager
.get_or_create(root.path(), Rkv::new::<Lmdb>)
.unwrap();
let created_dst_arc_1 = dst_manager.get_or_create(root.path(), Rkv::new::<Lmdb>).unwrap();
let dst_env_1 = created_dst_arc_1.read().unwrap();
populate_store!(&dst_env_1);
dst_env_1.sync(true).expect("synced");

File diff suppressed because it is too large Load Diff

View File

@ -15,37 +15,32 @@ use std::fs;
use serde_derive::Serialize;
use tempfile::Builder;
use rkv::{backend::SafeMode, PrimitiveInt, Rkv, StoreOptions, Value};
use rkv::{
backend::Lmdb,
PrimitiveInt,
Rkv,
StoreOptions,
Value,
};
#[test]
fn test_integer_keys() {
let root = Builder::new()
.prefix("test_integer_keys")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_integer_keys").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<SafeMode>(root.path()).expect("new succeeded");
let k = Rkv::new::<Lmdb>(root.path()).expect("new succeeded");
let s = k.open_integer("s", StoreOptions::create()).expect("open");
macro_rules! test_integer_keys {
($store:expr, $key:expr) => {{
let mut writer = k.write().expect("writer");
$store
.put(&mut writer, $key, &Value::Str("hello!"))
.expect("write");
assert_eq!(
$store.get(&writer, $key).expect("read"),
Some(Value::Str("hello!"))
);
$store.put(&mut writer, $key, &Value::Str("hello!")).expect("write");
assert_eq!($store.get(&writer, $key).expect("read"), Some(Value::Str("hello!")));
writer.commit().expect("committed");
let reader = k.read().expect("reader");
assert_eq!(
$store.get(&reader, $key).expect("read"),
Some(Value::Str("hello!"))
);
assert_eq!($store.get(&reader, $key).expect("read"), Some(Value::Str("hello!")));
}};
}

View File

@ -8,25 +8,34 @@
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
use std::{fs, sync::Arc};
use std::{
fs,
sync::Arc,
};
use tempfile::Builder;
#[cfg(feature = "lmdb")]
use rkv::backend::{Lmdb, LmdbEnvironment};
use rkv::{
backend::{BackendEnvironmentBuilder, SafeMode, SafeModeEnvironment},
CloseOptions, Rkv, StoreOptions, Value,
backend::{
BackendEnvironmentBuilder,
Lmdb,
LmdbEnvironment,
SafeMode,
SafeModeEnvironment,
},
CloseOptions,
Rkv,
StoreOptions,
Value,
};
/// Test that a manager can be created with simple type inference.
#[cfg(feature = "lmdb")]
#[test]
#[allow(clippy::let_underscore_lock)]
fn test_simple() {
type Manager = rkv::Manager<LmdbEnvironment>;
let _unused = Manager::singleton().write().unwrap();
let _ = Manager::singleton().write().unwrap();
}
/// Test that a manager can be created with simple type inference.
@ -35,25 +44,19 @@ fn test_simple() {
fn test_simple_safe() {
type Manager = rkv::Manager<SafeModeEnvironment>;
let _unused = Manager::singleton().write().unwrap();
let _ = Manager::singleton().write().unwrap();
}
/// Test that a shared Rkv instance can be created with simple type inference.
#[cfg(feature = "lmdb")]
#[test]
fn test_simple_2() {
type Manager = rkv::Manager<LmdbEnvironment>;
let root = Builder::new()
.prefix("test_simple_2")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_simple_2").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let mut manager = Manager::singleton().write().unwrap();
let _ = manager
.get_or_create(root.path(), Rkv::new::<Lmdb>)
.unwrap();
let _ = manager.get_or_create(root.path(), Rkv::new::<Lmdb>).unwrap();
}
/// Test that a shared Rkv instance can be created with simple type inference.
@ -61,49 +64,26 @@ fn test_simple_2() {
fn test_simple_safe_2() {
type Manager = rkv::Manager<SafeModeEnvironment>;
let root = Builder::new()
.prefix("test_simple_safe_2")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_simple_safe_2").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let mut manager = Manager::singleton().write().unwrap();
let _ = manager
.get_or_create(root.path(), Rkv::new::<SafeMode>)
.unwrap();
let _ = manager.get_or_create(root.path(), Rkv::new::<SafeMode>).unwrap();
}
/// Test that the manager will return the same Rkv instance each time for each path.
#[cfg(feature = "lmdb")]
#[test]
fn test_same() {
type Manager = rkv::Manager<LmdbEnvironment>;
let root = Builder::new()
.prefix("test_same")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_same").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let p = root.path();
assert!(Manager::singleton()
.read()
.unwrap()
.get(p)
.expect("success")
.is_none());
assert!(Manager::singleton().read().unwrap().get(p).expect("success").is_none());
let created_arc = Manager::singleton()
.write()
.unwrap()
.get_or_create(p, Rkv::new::<Lmdb>)
.expect("created");
let fetched_arc = Manager::singleton()
.read()
.unwrap()
.get(p)
.expect("success")
.expect("existed");
let created_arc = Manager::singleton().write().unwrap().get_or_create(p, Rkv::new::<Lmdb>).expect("created");
let fetched_arc = Manager::singleton().read().unwrap().get(p).expect("success").expect("existed");
assert!(Arc::ptr_eq(&created_arc, &fetched_arc));
}
@ -112,44 +92,23 @@ fn test_same() {
fn test_same_safe() {
type Manager = rkv::Manager<SafeModeEnvironment>;
let root = Builder::new()
.prefix("test_same_safe")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_same_safe").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let p = root.path();
assert!(Manager::singleton()
.read()
.unwrap()
.get(p)
.expect("success")
.is_none());
assert!(Manager::singleton().read().unwrap().get(p).expect("success").is_none());
let created_arc = Manager::singleton()
.write()
.unwrap()
.get_or_create(p, Rkv::new::<SafeMode>)
.expect("created");
let fetched_arc = Manager::singleton()
.read()
.unwrap()
.get(p)
.expect("success")
.expect("existed");
let created_arc = Manager::singleton().write().unwrap().get_or_create(p, Rkv::new::<SafeMode>).expect("created");
let fetched_arc = Manager::singleton().read().unwrap().get(p).expect("success").expect("existed");
assert!(Arc::ptr_eq(&created_arc, &fetched_arc));
}
/// Test that the manager will return the same Rkv instance each time for each path.
#[cfg(feature = "lmdb")]
#[test]
fn test_same_with_capacity() {
type Manager = rkv::Manager<LmdbEnvironment>;
let root = Builder::new()
.prefix("test_same_with_capacity")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_same_with_capacity").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let mut manager = Manager::singleton().write().unwrap();
@ -157,9 +116,7 @@ fn test_same_with_capacity() {
let p = root.path();
assert!(manager.get(p).expect("success").is_none());
let created_arc = manager
.get_or_create_with_capacity(p, 10, Rkv::with_capacity::<Lmdb>)
.expect("created");
let created_arc = manager.get_or_create_with_capacity(p, 10, Rkv::with_capacity::<Lmdb>).expect("created");
let fetched_arc = manager.get(p).expect("success").expect("existed");
assert!(Arc::ptr_eq(&created_arc, &fetched_arc));
}
@ -169,10 +126,7 @@ fn test_same_with_capacity() {
fn test_same_with_capacity_safe() {
type Manager = rkv::Manager<SafeModeEnvironment>;
let root = Builder::new()
.prefix("test_same_with_capacity_safe")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_same_with_capacity_safe").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let mut manager = Manager::singleton().write().unwrap();
@ -180,9 +134,7 @@ fn test_same_with_capacity_safe() {
let p = root.path();
assert!(manager.get(p).expect("success").is_none());
let created_arc = manager
.get_or_create_with_capacity(p, 10, Rkv::with_capacity::<SafeMode>)
.expect("created");
let created_arc = manager.get_or_create_with_capacity(p, 10, Rkv::with_capacity::<SafeMode>).expect("created");
let fetched_arc = manager.get(p).expect("success").expect("existed");
assert!(Arc::ptr_eq(&created_arc, &fetched_arc));
}
@ -193,33 +145,20 @@ fn test_same_with_capacity_safe() {
fn test_safe_mode_corrupt_while_open_1() {
type Manager = rkv::Manager<SafeModeEnvironment>;
let root = Builder::new()
.prefix("test_safe_mode_corrupt_while_open_1")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_safe_mode_corrupt_while_open_1").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
// Create environment.
let mut manager = Manager::singleton().write().unwrap();
let shared_env = manager
.get_or_create(root.path(), Rkv::new::<SafeMode>)
.expect("created");
let shared_env = manager.get_or_create(root.path(), Rkv::new::<SafeMode>).expect("created");
let env = shared_env.read().unwrap();
// Write some data.
let store = env
.open_single("store", StoreOptions::create())
.expect("opened");
let store = env.open_single("store", StoreOptions::create()).expect("opened");
let mut writer = env.write().expect("writer");
store
.put(&mut writer, "foo", &Value::I64(1234))
.expect("wrote");
store
.put(&mut writer, "bar", &Value::Bool(true))
.expect("wrote");
store
.put(&mut writer, "baz", &Value::Str("héllo, yöu"))
.expect("wrote");
store.put(&mut writer, "foo", &Value::I64(1234)).expect("wrote");
store.put(&mut writer, "bar", &Value::Bool(true)).expect("wrote");
store.put(&mut writer, "baz", &Value::Str("héllo, yöu")).expect("wrote");
writer.commit().expect("committed");
env.sync(true).expect("synced");
@ -234,23 +173,17 @@ fn test_safe_mode_corrupt_while_open_1() {
// Close everything.
drop(env);
drop(shared_env);
manager
.try_close(root.path(), CloseOptions::default())
.expect("closed without deleting");
manager.try_close(root.path(), CloseOptions::default()).expect("closed without deleting");
assert!(manager.get(root.path()).expect("success").is_none());
// Recreating environment fails.
manager
.get_or_create(root.path(), Rkv::new::<SafeMode>)
.expect_err("not created");
manager.get_or_create(root.path(), Rkv::new::<SafeMode>).expect_err("not created");
assert!(manager.get(root.path()).expect("success").is_none());
// But we can use a builder and pass `discard_if_corrupted` to deal with it.
let mut builder = Rkv::environment_builder::<SafeMode>();
builder.set_discard_if_corrupted(true);
manager
.get_or_create_from_builder(root.path(), builder, Rkv::from_builder::<SafeMode>)
.expect("created");
manager.get_or_create_from_builder(root.path(), builder, Rkv::from_builder::<SafeMode>).expect("created");
assert!(manager.get(root.path()).expect("success").is_some());
}
@ -260,33 +193,20 @@ fn test_safe_mode_corrupt_while_open_1() {
fn test_safe_mode_corrupt_while_open_2() {
type Manager = rkv::Manager<SafeModeEnvironment>;
let root = Builder::new()
.prefix("test_safe_mode_corrupt_while_open_2")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_safe_mode_corrupt_while_open_2").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
// Create environment.
let mut manager = Manager::singleton().write().unwrap();
let shared_env = manager
.get_or_create(root.path(), Rkv::new::<SafeMode>)
.expect("created");
let shared_env = manager.get_or_create(root.path(), Rkv::new::<SafeMode>).expect("created");
let env = shared_env.read().unwrap();
// Write some data.
let store = env
.open_single("store", StoreOptions::create())
.expect("opened");
let store = env.open_single("store", StoreOptions::create()).expect("opened");
let mut writer = env.write().expect("writer");
store
.put(&mut writer, "foo", &Value::I64(1234))
.expect("wrote");
store
.put(&mut writer, "bar", &Value::Bool(true))
.expect("wrote");
store
.put(&mut writer, "baz", &Value::Str("héllo, yöu"))
.expect("wrote");
store.put(&mut writer, "foo", &Value::I64(1234)).expect("wrote");
store.put(&mut writer, "bar", &Value::Bool(true)).expect("wrote");
store.put(&mut writer, "baz", &Value::Str("héllo, yöu")).expect("wrote");
writer.commit().expect("committed");
env.sync(true).expect("synced");
@ -299,82 +219,39 @@ fn test_safe_mode_corrupt_while_open_2() {
fs::write(&safebin, "bogus").expect("dbfile corrupted");
// Reading still works. Magic.
let store = env
.open_single("store", StoreOptions::default())
.expect("opened");
let store = env.open_single("store", StoreOptions::default()).expect("opened");
let reader = env.read().expect("reader");
assert_eq!(
store.get(&reader, "foo").expect("read"),
Some(Value::I64(1234))
);
assert_eq!(
store.get(&reader, "bar").expect("read"),
Some(Value::Bool(true))
);
assert_eq!(
store.get(&reader, "baz").expect("read"),
Some(Value::Str("héllo, yöu"))
);
assert_eq!(store.get(&reader, "foo").expect("read"), Some(Value::I64(1234)));
assert_eq!(store.get(&reader, "bar").expect("read"), Some(Value::Bool(true)));
assert_eq!(store.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")));
reader.abort();
// Writing still works, dbfile will be un-corrupted.
let store = env
.open_single("store", StoreOptions::default())
.expect("opened");
let store = env.open_single("store", StoreOptions::default()).expect("opened");
let mut writer = env.write().expect("writer");
store
.put(&mut writer, "foo2", &Value::I64(5678))
.expect("wrote");
store
.put(&mut writer, "bar2", &Value::Bool(false))
.expect("wrote");
store
.put(&mut writer, "baz2", &Value::Str("byé, yöu"))
.expect("wrote");
store.put(&mut writer, "foo2", &Value::I64(5678)).expect("wrote");
store.put(&mut writer, "bar2", &Value::Bool(false)).expect("wrote");
store.put(&mut writer, "baz2", &Value::Str("byé, yöu")).expect("wrote");
writer.commit().expect("committed");
env.sync(true).expect("synced");
// Close everything.
drop(env);
drop(shared_env);
manager
.try_close(root.path(), CloseOptions::default())
.expect("closed without deleting");
manager.try_close(root.path(), CloseOptions::default()).expect("closed without deleting");
assert!(manager.get(root.path()).expect("success").is_none());
// Recreate environment.
let shared_env = manager
.get_or_create(root.path(), Rkv::new::<SafeMode>)
.expect("created");
let shared_env = manager.get_or_create(root.path(), Rkv::new::<SafeMode>).expect("created");
let env = shared_env.read().unwrap();
// Verify that the dbfile is not corrupted.
let store = env
.open_single("store", StoreOptions::default())
.expect("opened");
let store = env.open_single("store", StoreOptions::default()).expect("opened");
let reader = env.read().expect("reader");
assert_eq!(
store.get(&reader, "foo").expect("read"),
Some(Value::I64(1234))
);
assert_eq!(
store.get(&reader, "bar").expect("read"),
Some(Value::Bool(true))
);
assert_eq!(
store.get(&reader, "baz").expect("read"),
Some(Value::Str("héllo, yöu"))
);
assert_eq!(
store.get(&reader, "foo2").expect("read"),
Some(Value::I64(5678))
);
assert_eq!(
store.get(&reader, "bar2").expect("read"),
Some(Value::Bool(false))
);
assert_eq!(
store.get(&reader, "baz2").expect("read"),
Some(Value::Str("byé, yöu"))
);
assert_eq!(store.get(&reader, "foo").expect("read"), Some(Value::I64(1234)));
assert_eq!(store.get(&reader, "bar").expect("read"), Some(Value::Bool(true)));
assert_eq!(store.get(&reader, "baz").expect("read"), Some(Value::Str("héllo, yöu")));
assert_eq!(store.get(&reader, "foo2").expect("read"), Some(Value::I64(5678)));
assert_eq!(store.get(&reader, "bar2").expect("read"), Some(Value::Bool(false)));
assert_eq!(store.get(&reader, "baz2").expect("read"), Some(Value::Str("byé, yöu")));
}

View File

@ -15,48 +15,36 @@ use std::fs;
use serde_derive::Serialize;
use tempfile::Builder;
use rkv::{backend::SafeMode, PrimitiveInt, Rkv, StoreOptions, Value};
use rkv::{
backend::Lmdb,
PrimitiveInt,
Rkv,
StoreOptions,
Value,
};
#[test]
fn test_multi_integer_keys() {
let root = Builder::new()
.prefix("test_integer_keys")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_integer_keys").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<SafeMode>(root.path()).expect("new succeeded");
let s = k
.open_multi_integer("s", StoreOptions::create())
.expect("open");
let k = Rkv::new::<Lmdb>(root.path()).expect("new succeeded");
let s = k.open_multi_integer("s", StoreOptions::create()).expect("open");
macro_rules! test_integer_keys {
($store:expr, $key:expr) => {{
let mut writer = k.write().expect("writer");
$store
.put(&mut writer, $key, &Value::Str("hello1"))
.expect("write");
$store
.put(&mut writer, $key, &Value::Str("hello2"))
.expect("write");
$store
.put(&mut writer, $key, &Value::Str("hello3"))
.expect("write");
$store.put(&mut writer, $key, &Value::Str("hello1")).expect("write");
$store.put(&mut writer, $key, &Value::Str("hello2")).expect("write");
$store.put(&mut writer, $key, &Value::Str("hello3")).expect("write");
let vals = $store
.get(&writer, $key)
.expect("read")
.map(|result| result.expect("ok"))
.map(|(_, v)| v)
.collect::<Vec<Value>>();
assert_eq!(
vals,
vec![
Value::Str("hello1"),
Value::Str("hello2"),
Value::Str("hello3")
]
);
assert_eq!(vals, vec![Value::Str("hello1"), Value::Str("hello2"), Value::Str("hello3")]);
writer.commit().expect("committed");
let reader = k.read().expect("reader");
@ -66,14 +54,7 @@ fn test_multi_integer_keys() {
.map(|result| result.expect("ok"))
.map(|(_, v)| v)
.collect::<Vec<Value>>();
assert_eq!(
vals,
vec![
Value::Str("hello1"),
Value::Str("hello2"),
Value::Str("hello3")
]
);
assert_eq!(vals, vec![Value::Str("hello1"), Value::Str("hello2"), Value::Str("hello3")]);
}};
}
@ -90,9 +71,7 @@ fn test_multi_integer_keys() {
// different integer key types, which may result in unexpected behavior.
// Make sure you know what you're doing!
let t = k
.open_multi_integer("s", StoreOptions::create())
.expect("open");
let t = k.open_multi_integer("s", StoreOptions::create()).expect("open");
#[derive(Serialize)]
struct I32(i32);
@ -100,9 +79,7 @@ fn test_multi_integer_keys() {
test_integer_keys!(t, I32(std::i32::MIN));
test_integer_keys!(t, I32(std::i32::MAX));
let u = k
.open_multi_integer("s", StoreOptions::create())
.expect("open");
let u = k.open_multi_integer("s", StoreOptions::create()).expect("open");
#[derive(Serialize)]
struct U16(u16);
@ -110,9 +87,7 @@ fn test_multi_integer_keys() {
test_integer_keys!(u, U16(std::u16::MIN));
test_integer_keys!(u, U16(std::u16::MAX));
let v = k
.open_multi_integer("s", StoreOptions::create())
.expect("open");
let v = k.open_multi_integer("s", StoreOptions::create()).expect("open");
#[derive(Serialize)]
struct U64(u64);

View File

@ -14,8 +14,17 @@ use std::fs;
use tempfile::Builder;
use rkv::{
backend::{SafeMode, SafeModeDatabase, SafeModeRoCursor, SafeModeRwTransaction},
Readable, Rkv, StoreOptions, Value, Writer,
backend::{
Lmdb,
LmdbDatabase,
LmdbRoCursor,
LmdbRwTransaction,
},
Readable,
Rkv,
StoreOptions,
Value,
Writer,
};
/// Consider a struct like this:
@ -32,17 +41,14 @@ use rkv::{
/// Note that the reader functions take `Readable` because they might run within a Read
/// Transaction or a Write Transaction. The test demonstrates fetching values via both.
type SingleStore = rkv::SingleStore<SafeModeDatabase>;
type MultiStore = rkv::MultiStore<SafeModeDatabase>;
type SingleStore = rkv::SingleStore<LmdbDatabase>;
type MultiStore = rkv::MultiStore<LmdbDatabase>;
#[test]
fn read_many() {
let root = Builder::new()
.prefix("test_txns")
.tempdir()
.expect("tempdir");
let root = Builder::new().prefix("test_txns").tempdir().expect("tempdir");
fs::create_dir_all(root.path()).expect("dir created");
let k = Rkv::new::<SafeMode>(root.path()).expect("new succeeded");
let k = Rkv::new::<Lmdb>(root.path()).expect("new succeeded");
let samplestore = k.open_single("s", StoreOptions::create()).expect("open");
let datestore = k.open_multi("m", StoreOptions::create()).expect("open");
let valuestore = k.open_multi("m", StoreOptions::create()).expect("open");
@ -51,8 +57,8 @@ fn read_many() {
let mut writer = k.write().expect("env write lock");
for id in 0..30_u64 {
let value = format!("value{id}");
let date = format!("2019-06-{id}");
let value = format!("value{}", id);
let date = format!("2019-06-{}", id);
put_id_field(&mut writer, datestore, &date, id);
put_id_field(&mut writer, valuestore, &value, id);
put_sample(&mut writer, samplestore, id, &value);
@ -60,47 +66,49 @@ fn read_many() {
// now we read in the same transaction
for id in 0..30_u64 {
let value = format!("value{id}");
let date = format!("2019-06-{id}");
let value = format!("value{}", id);
let date = format!("2019-06-{}", id);
let ids = get_ids_by_field(&writer, datestore, &date);
let ids2 = get_ids_by_field(&writer, valuestore, &value);
let samples = get_samples(&writer, samplestore, &ids);
let samples2 = get_samples(&writer, samplestore, &ids2);
println!("{samples:?}, {samples2:?}");
println!("{:?}, {:?}", samples, samples2);
}
}
{
let reader = k.read().expect("env read lock");
for id in 0..30_u64 {
let value = format!("value{id}");
let date = format!("2019-06-{id}");
let value = format!("value{}", id);
let date = format!("2019-06-{}", id);
let ids = get_ids_by_field(&reader, datestore, &date);
let ids2 = get_ids_by_field(&reader, valuestore, &value);
let samples = get_samples(&reader, samplestore, &ids);
let samples2 = get_samples(&reader, samplestore, &ids2);
println!("{samples:?}, {samples2:?}");
println!("{:?}, {:?}", samples, samples2);
}
}
}
fn get_ids_by_field<'t, T>(txn: &'t T, store: MultiStore, field: &'t str) -> Vec<u64>
where
T: Readable<'t, Database = SafeModeDatabase, RoCursor = SafeModeRoCursor<'t>>,
T: Readable<'t, Database = LmdbDatabase, RoCursor = LmdbRoCursor<'t>>,
{
store
.get(txn, field)
.expect("get iterator")
.map(|id| match id.expect("field") {
(_, Value::U64(id)) => id,
_ => panic!("getting value in iter"),
.map(|id| {
match id.expect("field") {
(_, Value::U64(id)) => id,
_ => panic!("getting value in iter"),
}
})
.collect::<Vec<u64>>()
}
fn get_samples<'t, T>(txn: &'t T, samplestore: SingleStore, ids: &[u64]) -> Vec<String>
where
T: Readable<'t, Database = SafeModeDatabase, RoCursor = SafeModeRoCursor<'t>>,
T: Readable<'t, Database = LmdbDatabase, RoCursor = LmdbRoCursor<'t>>,
{
ids.iter()
.map(|id| {
@ -114,18 +122,11 @@ where
.collect::<Vec<String>>()
}
fn put_sample(
txn: &mut Writer<SafeModeRwTransaction>,
samplestore: SingleStore,
id: u64,
value: &str,
) {
fn put_sample(txn: &mut Writer<LmdbRwTransaction>, samplestore: SingleStore, id: u64, value: &str) {
let idbytes = id.to_be_bytes();
samplestore
.put(txn, &idbytes, &Value::Str(value))
.expect("put id");
samplestore.put(txn, &idbytes, &Value::Str(value)).expect("put id");
}
fn put_id_field(txn: &mut Writer<SafeModeRwTransaction>, store: MultiStore, field: &str, id: u64) {
fn put_id_field(txn: &mut Writer<LmdbRwTransaction>, store: MultiStore, field: &str, id: u64) {
store.put(txn, field, &Value::U64(id)).expect("put id");
}

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "MPL-2.0"
[dependencies]
glean = "51.8.2"
glean = "51.8.1"
log = "0.4"
nserror = { path = "../../../xpcom/rust/nserror" }
nsstring = { path = "../../../xpcom/rust/nsstring" }

View File

@ -8,7 +8,7 @@ publish = false
[dependencies]
bincode = "1.0"
chrono = "0.4.10"
glean = "51.8.2"
glean = "51.8.1"
inherent = "1.0.0"
log = "0.4"
nsstring = { path = "../../../../xpcom/rust/nsstring", optional = true }

View File

@ -13,7 +13,7 @@ log = "0.4"
moz_task = { path = "../../../xpcom/rust/moz_task" }
nserror = { path = "../../../xpcom/rust/nserror" }
nsstring = { path = "../../../xpcom/rust/nsstring" }
rkv = { version = "0.18", default-features = false, features=["no-canonicalize-path"] }
rkv = { version = "0.17", default-features = false, features=["no-canonicalize-path"] }
storage_variant = { path = "../../../storage/variant" }
xpcom = { path = "../../../xpcom/rust/xpcom" }
tempfile = "3"

View File

@ -13,7 +13,7 @@ moz_task = { path = "../../../xpcom/rust/moz_task" }
nsstring = { path = "../../../xpcom/rust/nsstring" }
nserror = { path = "../../../xpcom/rust/nserror" }
once_cell = "1"
rkv = { version = "0.18", default-features = false, features=["no-canonicalize-path"] }
rkv = { version = "0.17", default-features = false, features=["no-canonicalize-path"] }
serde_json = "1"
tempfile = "3"
thiserror = "1"

View File

@ -7,5 +7,5 @@ authors = ["fuzzing@mozilla.com"]
libc = "0.2"
tempfile = "3"
lazy_static = "1.4.0"
rkv = { version = "0.18", features = ["with-fuzzer-no-link"] }
rkv = { version = "0.17", features = ["with-fuzzer-no-link"] }
lmdb-rkv = { version = "0.14", features = ["with-fuzzer-no-link"] }