message: Tokio update to 1.2.x version

diff:
@@ -79,31 +79,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4259cbe96513d2f1073027a259fc2ca917feb3026a5a8d984e3628e490255cc0"
dependencies = [
"extend",
- "serde 1.0.121",
+ "serde 1.0.123",
"serde_json",
]
-[[package]]
-name = "async-stream"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3670df70cbc01729f901f94c887814b3c68db038aad1329a418bae178bc5295c"
-dependencies = [
- "async-stream-impl",
- "futures-core",
-]
-
-[[package]]
-name = "async-stream-impl"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3548b8efc9f8e8a5a0a2808c5bd8451a9031b9e5b879a79590304ae928b0a70"
-dependencies = [
- "proc-macro2 1.0.24",
- "quote 1.0.8",
- "syn 1.0.59",
-]
-
[[package]]
name = "atty"
version = "0.2.14"
@@ -154,7 +133,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d"
dependencies = [
"byteorder",
- "serde 1.0.121",
+ "serde 1.0.123",
]
[[package]]
@@ -247,14 +226,14 @@ dependencies = [
[[package]]
name = "bstr"
-version = "0.2.14"
+version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "473fc6b38233f9af7baa94fb5852dca389e3d95b8e21c8e3719301462c5d9faf"
+checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d"
dependencies = [
"lazy_static",
"memchr",
"regex-automata",
- "serde 1.0.121",
+ "serde 1.0.123",
]
[[package]]
@@ -269,9 +248,9 @@ dependencies = [
[[package]]
name = "bumpalo"
-version = "3.5.0"
+version = "3.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f07aa6688c702439a1be0307b6a94dffe1168569e45b9500c1372bc580740d59"
+checksum = "099e596ef14349721d9016f6b80dd3419ea1bf289ab9b44df8e4dfd3a005d5d9"
[[package]]
name = "byte-tools"
@@ -309,9 +288,9 @@ dependencies = [
[[package]]
name = "bzip2-sys"
-version = "0.1.9+1.0.8"
+version = "0.1.10+1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad3b39a260062fca31f7b0b12f207e8f2590a67d32ec7d59c20484b07ea7285e"
+checksum = "17fa3d1ac1ca21c5c4e36a97f3c3eb25084576f6fc47bf0139c1123434216c6c"
dependencies = [
"cc",
"libc",
@@ -324,7 +303,7 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0"
dependencies = [
- "rustc_version",
+ "rustc_version 0.2.3",
]
[[package]]
@@ -366,7 +345,7 @@ dependencies = [
"libc",
"num-integer",
"num-traits 0.2.14",
- "serde 1.0.121",
+ "serde 1.0.123",
"time",
"winapi",
]
@@ -431,7 +410,7 @@ dependencies = [
"lazy_static",
"nom",
"rust-ini",
- "serde 1.0.121",
+ "serde 1.0.123",
"serde-hjson",
"serde_json",
"toml",
@@ -495,23 +474,23 @@ dependencies = [
[[package]]
name = "criterion"
-version = "0.3.3"
+version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70daa7ceec6cf143990669a04c7df13391d55fb27bd4079d252fca774ba244d8"
+checksum = "ab327ed7354547cc2ef43cbe20ef68b988e70b4b593cbd66a2a61733123a3d23"
dependencies = [
"atty",
"cast",
"clap",
"criterion-plot",
"csv",
- "itertools 0.9.0",
+ "itertools 0.10.0",
"lazy_static",
"num-traits 0.2.14",
"oorandom",
"plotters",
"rayon",
"regex",
- "serde 1.0.121",
+ "serde 1.0.123",
"serde_cbor",
"serde_derive",
"serde_json",
@@ -616,7 +595,7 @@ dependencies = [
"num-bigint",
"num-traits 0.2.14",
"rand 0.7.3",
- "serde 1.0.121",
+ "serde 1.0.123",
"sodiumoxide",
]
@@ -640,7 +619,7 @@ dependencies = [
"csv-core",
"itoa",
"ryu",
- "serde 1.0.121",
+ "serde 1.0.123",
]
[[package]]
@@ -689,7 +668,7 @@ dependencies = [
"proc-macro2 1.0.24",
"quote 1.0.8",
"strsim 0.9.3",
- "syn 1.0.59",
+ "syn 1.0.60",
]
[[package]]
@@ -700,7 +679,7 @@ checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
dependencies = [
"darling_core",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
]
[[package]]
@@ -724,7 +703,7 @@ dependencies = [
"derive_builder_core",
"proc-macro2 1.0.24",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
]
[[package]]
@@ -736,7 +715,7 @@ dependencies = [
"darling",
"proc-macro2 1.0.24",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
]
[[package]]
@@ -813,7 +792,7 @@ checksum = "1e94aa31f7c0dc764f57896dc615ddd76fc13b0d5dca7eb6cc5e018a5a09ec06"
dependencies = [
"proc-macro2 1.0.24",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
]
[[package]]
@@ -835,7 +814,7 @@ version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0465971a8cc1fa2455c8465aaa377131e1f1cf4983280f474a13e68793aa770c"
dependencies = [
- "serde 1.0.121",
+ "serde 1.0.123",
]
[[package]]
@@ -847,7 +826,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2 1.0.24",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
]
[[package]]
@@ -868,7 +847,7 @@ checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
dependencies = [
"proc-macro2 1.0.24",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
"synstructure",
]
@@ -970,7 +949,7 @@ dependencies = [
"proc-macro-hack",
"proc-macro2 1.0.24",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
]
[[package]]
@@ -1155,7 +1134,7 @@ checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
dependencies = [
"cfg-if 1.0.0",
"libc",
- "wasi 0.10.1+wasi-snapshot-preview1",
+ "wasi 0.10.2+wasi-snapshot-preview1",
]
[[package]]
@@ -1167,7 +1146,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2 1.0.24",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
]
[[package]]
@@ -1297,9 +1276,9 @@ dependencies = [
[[package]]
name = "httparse"
-version = "1.3.4"
+version = "1.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
+checksum = "615caabe2c3160b313d52ccc905335f4ed5f10881dd63dc5699d47e90be85691"
[[package]]
name = "httpdate"
@@ -1318,9 +1297,9 @@ dependencies = [
[[package]]
name = "hyper"
-version = "0.14.2"
+version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "12219dc884514cb4a6a03737f4413c0e01c23a1b059b0156004b23f1e19dccbe"
+checksum = "e8e946c2b1349055e0b72ae281b238baf1a3ea7307c7e9f9d64673bdd9c26ac7"
dependencies = [
"bytes 1.0.1",
"futures-channel",
@@ -1332,7 +1311,7 @@ dependencies = [
"httparse",
"httpdate",
"itoa",
- "pin-project 1.0.4",
+ "pin-project 1.0.5",
"socket2",
"tokio",
"tower-service",
@@ -1348,9 +1327,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
-version = "0.2.0"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
+checksum = "de910d521f7cc3135c4de8db1cb910e0b5ed1dc6f57c381cd07e8e661ce10094"
dependencies = [
"matches",
"unicode-bidi",
@@ -1395,7 +1374,7 @@ dependencies = [
"ipmpsc",
"libc",
"rand 0.7.3",
- "serde 1.0.121",
+ "serde 1.0.123",
"serial_test",
]
@@ -1409,7 +1388,7 @@ dependencies = [
"hex",
"libc",
"memmap",
- "serde 1.0.121",
+ "serde 1.0.123",
"sha2",
"tempfile",
"thiserror",
@@ -1452,9 +1431,9 @@ dependencies = [
[[package]]
name = "js-sys"
-version = "0.3.46"
+version = "0.3.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf3d7383929f7c9c7c2d0fa596f325832df98c3704f2c60553080f7127a58175"
+checksum = "5cfb73131c35423a367daf8cbd24100af0d077668c8c2943f0e7dd775fef0f65"
dependencies = [
"wasm-bindgen",
]
@@ -1486,9 +1465,9 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.82"
+version = "0.2.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929"
+checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
[[package]]
name = "libflate"
@@ -1596,11 +1575,11 @@ dependencies = [
[[package]]
name = "log"
-version = "0.4.13"
+version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2"
+checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
- "cfg-if 0.1.10",
+ "cfg-if 1.0.0",
]
[[package]]
@@ -1610,7 +1589,7 @@ dependencies = [
"chrono",
"libflate",
"nix 0.19.1",
- "serde 1.0.121",
+ "serde 1.0.123",
"slog",
"slog-json",
"tempfile",
@@ -1672,7 +1651,7 @@ dependencies = [
"proc-macro-error",
"proc-macro2 1.0.24",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
]
[[package]]
@@ -1743,7 +1722,7 @@ dependencies = [
"networking",
"rand 0.7.3",
"riker",
- "serde 1.0.121",
+ "serde 1.0.123",
"serde_json",
"shell",
"slog",
@@ -1844,7 +1823,7 @@ dependencies = [
"num-integer",
"num-traits 0.2.14",
"rand 0.7.3",
- "serde 1.0.121",
+ "serde 1.0.123",
]
[[package]]
@@ -1995,6 +1974,15 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
+[[package]]
+name = "pest"
+version = "2.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
+dependencies = [
+ "ucd-trie",
+]
+
[[package]]
name = "pin-project"
version = "0.4.27"
@@ -2006,11 +1994,11 @@ dependencies = [
[[package]]
name = "pin-project"
-version = "1.0.4"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95b70b68509f17aa2857863b6fa00bf21fc93674c7a8893de2f469f6aa7ca2f2"
+checksum = "96fa8ebb90271c4477f144354485b8068bd8f6b78b428b01ba892ca26caf0b63"
dependencies = [
- "pin-project-internal 1.0.4",
+ "pin-project-internal 1.0.5",
]
[[package]]
@@ -2021,18 +2009,18 @@ checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895"
dependencies = [
"proc-macro2 1.0.24",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
]
[[package]]
name = "pin-project-internal"
-version = "1.0.4"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "caa25a6393f22ce819b0f50e0be89287292fda8d425be38ee0ca14c4931d9e71"
+checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b"
dependencies = [
"proc-macro2 1.0.24",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
]
[[package]]
@@ -2055,16 +2043,32 @@ checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]]
name = "plotters"
-version = "0.2.15"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d1685fbe7beba33de0330629da9d955ac75bd54f33d7b79f9a895590124f6bb"
+checksum = "45ca0ae5f169d0917a7c7f5a9c1a3d3d9598f18f529dd2b8373ed988efea307a"
dependencies = [
- "js-sys",
"num-traits 0.2.14",
+ "plotters-backend",
+ "plotters-svg",
"wasm-bindgen",
"web-sys",
]
+[[package]]
+name = "plotters-backend"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b07fffcddc1cb3a1de753caa4e4df03b79922ba43cf882acc1bdd7e8df9f4590"
+
+[[package]]
+name = "plotters-svg"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b38a02e23bd9604b842a812063aec4ef702b57989c37b655254bb61c471ad211"
+dependencies = [
+ "plotters-backend",
+]
+
[[package]]
name = "ppv-lite86"
version = "0.2.10"
@@ -2080,7 +2084,7 @@ dependencies = [
"proc-macro-error-attr",
"proc-macro2 1.0.24",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
"version_check",
]
@@ -2195,9 +2199,9 @@ dependencies = [
[[package]]
name = "rand"
-version = "0.8.2"
+version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18519b42a40024d661e1714153e9ad0c3de27cd495760ceb09710920f1098b1e"
+checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
dependencies = [
"libc",
"rand_chacha 0.3.0",
@@ -2424,7 +2428,7 @@ dependencies = [
"rand 0.7.3",
"rayon",
"riker",
- "serde 1.0.121",
+ "serde 1.0.123",
"serde_json",
"shell",
"slog",
@@ -2472,7 +2476,16 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
- "semver",
+ "semver 0.9.0",
+]
+
+[[package]]
+name = "rustc_version"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee"
+dependencies = [
+ "semver 0.11.0",
]
[[package]]
@@ -2508,7 +2521,7 @@ dependencies = [
"nix 0.19.1",
"os_type",
"rand 0.7.3",
- "serde 1.0.121",
+ "serde 1.0.123",
"serde_json",
"sha2",
"slog",
@@ -2546,7 +2559,16 @@ version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
- "semver-parser",
+ "semver-parser 0.7.0",
+]
+
+[[package]]
+name = "semver"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6"
+dependencies = [
+ "semver-parser 0.10.2",
]
[[package]]
@@ -2555,6 +2577,15 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+[[package]]
+name = "semver-parser"
+version = "0.10.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7"
+dependencies = [
+ "pest",
+]
+
[[package]]
name = "serde"
version = "0.8.23"
@@ -2563,9 +2594,9 @@ checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8"
[[package]]
name = "serde"
-version = "1.0.121"
+version = "1.0.123"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6159e3c76cab06f6bc466244d43b35e77e9500cd685da87620addadc2a4c40b1"
+checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae"
dependencies = [
"serde_derive",
]
@@ -2590,29 +2621,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622"
dependencies = [
"half",
- "serde 1.0.121",
+ "serde 1.0.123",
]
[[package]]
name = "serde_derive"
-version = "1.0.121"
+version = "1.0.123"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3fcab8778dc651bc65cfab2e4eb64996f3c912b74002fb379c94517e1f27c46"
+checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31"
dependencies = [
"proc-macro2 1.0.24",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
]
[[package]]
name = "serde_json"
-version = "1.0.61"
+version = "1.0.62"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a"
+checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486"
dependencies = [
"itoa",
"ryu",
- "serde 1.0.121",
+ "serde 1.0.123",
]
[[package]]
@@ -2633,7 +2664,7 @@ dependencies = [
"form_urlencoded",
"itoa",
"ryu",
- "serde 1.0.121",
+ "serde 1.0.123",
]
[[package]]
@@ -2655,7 +2686,7 @@ checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5"
dependencies = [
"proc-macro2 1.0.24",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
]
[[package]]
@@ -2672,9 +2703,9 @@ dependencies = [
[[package]]
name = "sha-1"
-version = "0.9.2"
+version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce3cdf1b5e620a498ee6f2a171885ac7e22f0e12089ec4b3d22b84921792507c"
+checksum = "f4b312c3731e3fe78a185e6b9b911a7aa715b8e31cce117975219aab2acf285d"
dependencies = [
"block-buffer 0.9.0",
"cfg-if 1.0.0",
@@ -2685,9 +2716,9 @@ dependencies = [
[[package]]
name = "sha2"
-version = "0.9.2"
+version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e7aab86fe2149bad8c507606bdb3f4ef5e7b2380eb92350f56122cca72a42a8"
+checksum = "fa827a14b29ab7f44778d14a88d3cb76e949c45083f7dbfa507d0cb699dc12de"
dependencies = [
"block-buffer 0.9.0",
"cfg-if 1.0.0",
@@ -2716,7 +2747,7 @@ dependencies = [
"rand 0.7.3",
"regex",
"riker",
- "serde 1.0.121",
+ "serde 1.0.123",
"serde_json",
"serial_test",
"slog",
@@ -2783,7 +2814,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddc0d2aff1f8f325ef660d9a0eb6e6dcd20b30b3f581a5897f58bf42d061c37a"
dependencies = [
"chrono",
- "serde 1.0.121",
+ "serde 1.0.123",
"serde_json",
"slog",
]
@@ -2812,9 +2843,9 @@ dependencies = [
[[package]]
name = "slog-term"
-version = "2.6.0"
+version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bab1d807cf71129b05ce36914e1dbb6fbfbdecaf686301cb457f4fa967f9f5b6"
+checksum = "c76d88c965d3c60da712ef89ba2bca3fd118ed6dead726a9b7153eaddd7a56b1"
dependencies = [
"atty",
"chrono",
@@ -2859,7 +2890,7 @@ checksum = "7038b67c941e23501573cb7242ffb08709abe9b11eb74bceff875bbda024a6a8"
dependencies = [
"libc",
"libsodium-sys",
- "serde 1.0.121",
+ "serde 1.0.123",
]
[[package]]
@@ -2887,7 +2918,7 @@ dependencies = [
"num_cpus",
"rand 0.7.3",
"rocksdb",
- "serde 1.0.121",
+ "serde 1.0.123",
"serde_json",
"slog",
"slog-async",
@@ -2924,7 +2955,7 @@ dependencies = [
"heck",
"proc-macro2 1.0.24",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
]
[[package]]
@@ -2946,9 +2977,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "1.0.59"
+version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07cb8b1b4ebf86a89ee88cbd201b022b94138c623644d035185c84d3f41b7e66"
+checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
dependencies = [
"proc-macro2 1.0.24",
"quote 1.0.8",
@@ -2963,7 +2994,7 @@ checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701"
dependencies = [
"proc-macro2 1.0.24",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
"unicode-xid 0.2.1",
]
@@ -2981,7 +3012,7 @@ checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
dependencies = [
"cfg-if 1.0.0",
"libc",
- "rand 0.8.2",
+ "rand 0.8.3",
"redox_syscall 0.2.4",
"remove_dir_all",
"winapi",
@@ -3028,7 +3059,7 @@ dependencies = [
"hex",
"lazy_static",
"ocaml-interop",
- "serde 1.0.121",
+ "serde 1.0.123",
"serde_json",
"tezos_messages",
]
@@ -3055,7 +3086,7 @@ version = "0.9.3"
dependencies = [
"crossbeam",
"lazy_static",
- "serde 1.0.121",
+ "serde 1.0.123",
]
[[package]]
@@ -3071,7 +3102,7 @@ dependencies = [
"hex",
"num-bigint",
"num-traits 0.2.14",
- "serde 1.0.121",
+ "serde 1.0.123",
]
[[package]]
@@ -3083,7 +3114,7 @@ dependencies = [
"failure",
"failure_derive",
"hex",
- "serde 1.0.121",
+ "serde 1.0.123",
"serde_json",
]
@@ -3101,7 +3132,7 @@ dependencies = [
"lazy_static",
"ocaml-interop",
"os_type",
- "serde 1.0.121",
+ "serde 1.0.123",
"serde_json",
"serial_test",
"sha2",
@@ -3136,7 +3167,7 @@ dependencies = [
"lazy_static",
"num-bigint",
"num-traits 0.2.14",
- "serde 1.0.121",
+ "serde 1.0.123",
"serde_json",
"strum",
"strum_macros",
@@ -3157,7 +3188,7 @@ dependencies = [
"nix 0.19.1",
"r2d2",
"rand 0.7.3",
- "serde 1.0.121",
+ "serde 1.0.123",
"slog",
"strum_macros",
"tezos_api",
@@ -3182,14 +3213,14 @@ checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1"
dependencies = [
"proc-macro2 1.0.24",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
]
[[package]]
name = "thread_local"
-version = "1.1.1"
+version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "301bdd13d23c49672926be451130892d274d3ba0b410c18e00daa7990ff38d99"
+checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
dependencies = [
"once_cell",
]
@@ -3219,15 +3250,15 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2ada8616fad06a2d0c455adc530de4ef57605a8120cc65da9653e0e9623ca74"
dependencies = [
- "serde 1.0.121",
+ "serde 1.0.123",
"serde_json",
]
[[package]]
name = "tinyvec"
-version = "1.1.0"
+version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ccf8dbc19eb42fba10e8feaaec282fb50e2c14b2726d6301dbfeed0f73306a6f"
+checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023"
dependencies = [
"tinyvec_macros",
]
@@ -3240,9 +3271,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
-version = "1.1.0"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8efab2086f17abcddb8f756117665c958feee6b2e39974c2f1600592ab3a4195"
+checksum = "e8190d04c665ea9e6b6a0dc45523ade572c088d2e6566244c1122671dbf4ae3a"
dependencies = [
"autocfg",
"bytes 1.0.1",
@@ -3260,20 +3291,20 @@ dependencies = [
[[package]]
name = "tokio-macros"
-version = "1.0.0"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42517d2975ca3114b22a16192634e8241dc5cc1f130be194645970cc1c371494"
+checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57"
dependencies = [
"proc-macro2 1.0.24",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
]
[[package]]
name = "tokio-stream"
-version = "0.1.2"
+version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76066865172052eb8796c686f0b441a93df8b08d40a950b062ffb9a426f00edd"
+checksum = "1981ad97df782ab506a1f43bf82c967326960d278acf3bf8279809648c3ff3ea"
dependencies = [
"futures-core",
"pin-project-lite",
@@ -3288,25 +3319,23 @@ checksum = "e1a5f475f1b9d077ea1017ecbc60890fda8e54942d680ca0b1d2b47cfa2d861b"
dependencies = [
"futures-util",
"log",
- "pin-project 1.0.4",
+ "pin-project 1.0.5",
"tokio",
"tungstenite",
]
[[package]]
name = "tokio-util"
-version = "0.6.2"
+version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "feb971a26599ffd28066d387f109746df178eff14d5ea1e235015c5601967a4b"
+checksum = "ebb7cb2f00c5ae8df755b252306272cd1790d39728363936e01827e11f0b017b"
dependencies = [
- "async-stream",
"bytes 1.0.1",
"futures-core",
"futures-sink",
"log",
"pin-project-lite",
"tokio",
- "tokio-stream",
]
[[package]]
@@ -3315,7 +3344,7 @@ version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
dependencies = [
- "serde 1.0.121",
+ "serde 1.0.123",
]
[[package]]
@@ -3326,9 +3355,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
[[package]]
name = "tracing"
-version = "0.1.22"
+version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f47026cdc4080c07e49b37087de021820269d996f581aac150ef9e5583eefe3"
+checksum = "f7d40a22fd029e33300d8d89a5cc8ffce18bb7c587662f54629e94c9de5487f3"
dependencies = [
"cfg-if 1.0.0",
"log",
@@ -3374,8 +3403,8 @@ dependencies = [
"httparse",
"input_buffer",
"log",
- "rand 0.8.2",
- "sha-1 0.9.2",
+ "rand 0.8.3",
+ "sha-1 0.9.3",
"url",
"utf-8",
]
@@ -3395,6 +3424,12 @@ version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
+[[package]]
+name = "ucd-trie"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
+
[[package]]
name = "unicase"
version = "2.6.0"
@@ -3415,9 +3450,9 @@ dependencies = [
[[package]]
name = "unicode-normalization"
-version = "0.1.16"
+version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a13e63ab62dbe32aeee58d1c5408d35c36c392bba5d9d3142287219721afe606"
+checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef"
dependencies = [
"tinyvec",
]
@@ -3471,7 +3506,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
dependencies = [
"getrandom 0.2.2",
- "serde 1.0.121",
+ "serde 1.0.123",
]
[[package]]
@@ -3482,12 +3517,13 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "vergen"
-version = "3.1.0"
+version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ce50d8996df1f85af15f2cd8d33daae6e479575123ef4314a51a70a230739cb"
+checksum = "e7141e445af09c8919f1d5f8a20dae0b20c3b57a45dee0d5823c6ed5d237f15a"
dependencies = [
"bitflags",
"chrono",
+ "rustc_version 0.3.3",
]
[[package]]
@@ -3542,9 +3578,9 @@ dependencies = [
"mime_guess",
"multipart",
"percent-encoding",
- "pin-project 1.0.4",
+ "pin-project 1.0.5",
"scoped-tls",
- "serde 1.0.121",
+ "serde 1.0.123",
"serde_json",
"serde_urlencoded",
"tokio",
@@ -3564,15 +3600,15 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
[[package]]
name = "wasi"
-version = "0.10.1+wasi-snapshot-preview1"
+version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93c6c3420963c5c64bca373b25e77acb562081b9bb4dd5bb864187742186cea9"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
name = "wasm-bindgen"
-version = "0.2.69"
+version = "0.2.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e"
+checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen-macro",
@@ -3580,24 +3616,24 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.69"
+version = "0.2.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1114f89ab1f4106e5b55e688b828c0ab0ea593a1ea7c094b141b14cbaaec2d62"
+checksum = "7bc45447f0d4573f3d65720f636bbcc3dd6ce920ed704670118650bcd47764c7"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"proc-macro2 1.0.24",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.69"
+version = "0.2.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084"
+checksum = "3b8853882eef39593ad4174dd26fc9865a64e84026d223f63bb2c42affcbba2c"
dependencies = [
"quote 1.0.8",
"wasm-bindgen-macro-support",
@@ -3605,28 +3641,28 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.69"
+version = "0.2.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549"
+checksum = "4133b5e7f2a531fa413b3a1695e925038a05a71cf67e87dafa295cb645a01385"
dependencies = [
"proc-macro2 1.0.24",
"quote 1.0.8",
- "syn 1.0.59",
+ "syn 1.0.60",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.69"
+version = "0.2.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158"
+checksum = "dd4945e4943ae02d15c13962b38a5b1e81eadd4b71214eee75af64a4d6a4fd64"
[[package]]
name = "web-sys"
-version = "0.3.46"
+version = "0.3.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "222b1ef9334f92a21d3fb53dc3fd80f30836959a90f9274a626d7e06315ba3c3"
+checksum = "c40dc691fc48003eba817c38da7113c15698142da971298003cac3ef175680b3"
dependencies = [
"js-sys",
"wasm-bindgen",

diff:
@@ -17,7 +17,7 @@ slog = { version = "2.7", features = ["max_level_trace"] }
slog-async = "2.6"
slog-json = "2.3"
slog-term = "2.6"
-tokio = { version = "1.1", features = ["rt-multi-thread", "signal"] }
+tokio = { version = "1.2", features = ["rt-multi-thread", "signal"] }
# Local dependencies
logging = { path = "../logging" }
tezos_api = { path = "../tezos/api" }

diff:
@@ -16,7 +16,7 @@ crypto = { path = "../crypto" }
networking = { path = "../networking" }
shell = { path = "../shell" }
tezos_messages = { path = "../tezos/messages" }
-tokio = { version = "1.1", features = ["full"] }
+tokio = { version = "1.2", features = ["full"] }
tokio-stream = "0.1.2"
futures = { version = "0.3", default-features = false }
warp = "0.3"

diff:
@@ -11,7 +11,7 @@ futures = "0.3"
hex = "0.4"
riker = "0.4"
slog = "2.7"
-tokio = { version = "1.1", features = ["time", "net"] }
+tokio = { version = "1.2", features = ["time", "net"] }
# local dependencies
crypto = { path = "../crypto" }
tezos_encoding = { path = "../tezos/encoding" }

diff:
@@ -18,7 +18,7 @@ riker = "0.4"
serde = { version = "1.0", features = ["derive", "rc"] }
serde_json = "1.0"
slog = { version = "2.7", features = ["nested-values"] }
-tokio = { version = "1.1", features = ["time"] }
+tokio = { version = "1.2", features = ["time"] }
rayon = "1.5"
# local dependencies
crypto = { path = "../crypto" }
@@ -35,4 +35,4 @@ enum-iterator = "0.6"
lazy_static = "1.4"
rand = "0.7.3"
hyper = { version = "0.14", features = ["client"] }
-tokio = { version = "1.1", features = ["macros"] }
\ No newline at end of file
+tokio = { version = "1.2", features = ["macros"] }

diff:
@@ -16,7 +16,7 @@ serde_json = "1.0"
slog = { version = "2.7", features = ["nested-values"] }
slog-async = "2.6"
slog-term = "2.6"
-tokio = { version = "1.1", features = ["full"] }
+tokio = { version = "1.2", features = ["full"] }
warp = "0.3"
wait-timeout = "0.2"

diff:
@@ -21,7 +21,7 @@ riker = "0.4"
slog = "2.7"
serde = "1.0"
serde_json = "1.0"
-tokio = { version = "1.1", features = ["time"] }
+tokio = { version = "1.2", features = ["time"] }
# local dependencies
crypto = { path = "../crypto" }
networking = { path = "../networking" }

original_message: Tokio update to 1.2.x version


message: support for different key value backends

change_type: MODIFY

diff:
@@ -885,6 +885,16 @@ dependencies = [
"percent-encoding",
]
+[[package]]
+name = "fs2"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
[[package]]
name = "fs_extra"
version = "1.2.0"
@@ -1096,6 +1106,15 @@ dependencies = [
"tezos_messages",
]
+[[package]]
+name = "fxhash"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c"
+dependencies = [
+ "byteorder",
+]
+
[[package]]
name = "generic-array"
version = "0.12.3"
@@ -2789,6 +2808,22 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
+[[package]]
+name = "sled"
+version = "0.34.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d0132f3e393bcb7390c60bb45769498cf4550bcb7a21d7f95c02b69f6362cdc"
+dependencies = [
+ "crc32fast",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+ "fs2",
+ "fxhash",
+ "libc",
+ "log",
+ "parking_lot",
+]
+
[[package]]
name = "slog"
version = "2.7.0"
@@ -2930,6 +2965,7 @@ dependencies = [
"rocksdb",
"serde 1.0.123",
"serde_json",
+ "sled",
"slog",
"slog-async",
"slog-term",

diff:
@@ -16,6 +16,7 @@ use rocksdb::ColumnFamilyDescriptor;
use shell::peer_manager::P2p;
use shell::PeerConnectionThreshold;
use storage::persistent::KeyValueSchema;
+use storage::KeyValueStoreBackend;
use tezos_api::environment;
use tezos_api::environment::TezosEnvironment;
use tezos_api::ffi::PatchContext;
@@ -111,6 +112,7 @@ pub struct Storage {
pub db_path: PathBuf,
pub tezos_data_dir: PathBuf,
pub action_store_backend: Vec<ContextActionStoreBackend>,
+ pub kv_store_backend: KeyValueStoreBackend,
pub compute_context_action_tree_hashes: bool,
pub patch_context: Option<PatchContext>,
}
@@ -865,6 +867,7 @@ impl Environment {
h
}
};
+
let action_store_backend = backends
.iter()
.map(|name| match name.as_str() {
@@ -880,6 +883,14 @@ impl Environment {
})
.collect();
+ let kv_store_backend = match args.value_of("kv-store-backend").unwrap_or("rocksdb")
+ {
+ "inmem" => KeyValueStoreBackend::InMem,
+ "sled" => KeyValueStoreBackend::Sled,
+ "btree" => KeyValueStoreBackend::BTreeMap,
+ _ => KeyValueStoreBackend::RocksDB,
+ };
+
crate::configuration::Storage {
tezos_data_dir: data_dir.clone(),
db,
@@ -888,6 +899,7 @@ impl Environment {
db_path,
compute_context_action_tree_hashes,
action_store_backend,
+ kv_store_backend,
patch_context: {
match args.value_of("sandbox-patch-context-json-file") {
Some(path) => {

diff:
@@ -35,6 +35,7 @@ use storage::persistent::{
};
use storage::ActionFileStorage;
use storage::ContextActionStorage;
+use storage::KeyValueStoreBackend;
use storage::{
check_database_compatibility, context::TezedgeContext, persistent::DBError,
resolve_storage_init_chain_data, BlockStorage, StorageInitInfo,
@@ -593,7 +594,13 @@ fn main() {
);
{
- let persistent_storage = PersistentStorage::new(kv, kv_context, kv_actions, commit_logs);
+ let persistent_storage = PersistentStorage::new(
+ kv,
+ kv_context,
+ kv_actions,
+ commit_logs,
+ env.storage.kv_store_backend.clone(),
+ );
let tezedge_context = TezedgeContext::new(
BlockStorage::new(&persistent_storage),
persistent_storage.merkle(),

diff:
@@ -23,6 +23,7 @@ snap = "1.0.4"
tezos_api = { path = "../tezos/api" }
tezos_context = { path = "../tezos/context" }
tezos_messages = { path = "../tezos/messages" }
+sled = "0.34.6"
bytes = "1.0.1"
[[bench]]

change_type: ADD

diff:
+use std::collections::{btree_map::Entry, BTreeMap, HashSet};
+
+use crate::merkle_storage::{ContextValue, EntryHash};
+use crate::persistent::database::RocksDBStats;
+use crate::storage_backend::{
+ StorageBackend as KVStoreTrait, StorageBackendError as KVStoreError,
+ StorageBackendStats as KVStoreStats,
+};
+
+/// In Memory Key Value Store implemented with [BTreeMap](std::collections::BTreeMap)
+#[derive(Debug)]
+pub struct KVStore<K: Ord, V> {
+ kv_map: BTreeMap<K, V>,
+}
+
+impl<K: Ord, V> Default for KVStore<K, V> {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl<K: Ord, V> KVStore<K, V> {
+ pub fn new() -> Self {
+ Self {
+ kv_map: BTreeMap::new(),
+ }
+ }
+}
+
+impl KVStoreTrait for KVStore<EntryHash, ContextValue> {
+ fn is_persisted(&self) -> bool {
+ false
+ }
+
+ /// put kv in map if key doesn't exist. If it does then return false.
+ fn put(&mut self, key: EntryHash, value: ContextValue) -> Result<bool, KVStoreError> {
+ match self.kv_map.entry(key) {
+ Entry::Vacant(entry) => {
+ entry.insert(value);
+ Ok(true)
+ }
+ _ => Ok(false),
+ }
+ }
+
+ fn merge(&mut self, key: EntryHash, value: ContextValue) -> Result<(), KVStoreError> {
+ self.kv_map.insert(key, value);
+ Ok(())
+ }
+
+ fn delete(&mut self, key: &EntryHash) -> Result<Option<ContextValue>, KVStoreError> {
+ Ok(self.kv_map.remove(key))
+ }
+
+ fn get(&self, key: &EntryHash) -> Result<Option<ContextValue>, KVStoreError> {
+ Ok(self.kv_map.get(key).cloned())
+ }
+
+ fn contains(&self, key: &EntryHash) -> Result<bool, KVStoreError> {
+ Ok(self.kv_map.contains_key(key))
+ }
+
+ fn get_mem_use_stats(&self) -> Result<RocksDBStats, KVStoreError> {
+ Ok(RocksDBStats {
+ mem_table_total: 0,
+ mem_table_unflushed: 0,
+ mem_table_readers_total: 0,
+ cache_total: 0,
+ })
+ }
+}
+
+pub type BTreeMapBackend = KVStore<EntryHash, ContextValue>;

diff:
+// use rayon::prelude::*;
+use std::collections::HashMap;
+use std::sync::{Arc, RwLock};
+
+use crate::merkle_storage::{ContextValue, EntryHash};
+use crate::persistent::database::RocksDBStats;
+use crate::storage_backend::{StorageBackend, StorageBackendError, StorageBackendStats};
+
+#[derive(Default)]
+pub struct InMemoryBackend {
+ inner: Arc<RwLock<HashMap<EntryHash, ContextValue>>>,
+ stats: StorageBackendStats,
+}
+
+impl InMemoryBackend {
+ pub fn new() -> Self {
+ InMemoryBackend {
+ inner: Arc::new(RwLock::new(HashMap::new())),
+ stats: Default::default(),
+ }
+ }
+}
+
+impl StorageBackend for InMemoryBackend {
+ fn is_persisted(&self) -> bool {
+ false
+ }
+
+ fn put(&mut self, key: EntryHash, value: ContextValue) -> Result<bool, StorageBackendError> {
+ let measurement = StorageBackendStats::from((&key, &value));
+ let mut w = self
+ .inner
+ .write()
+ .map_err(|e| StorageBackendError::GuardPoison {
+ error: format!("{}", e),
+ })?;
+
+ let was_added = w.insert(key, value).is_none();
+
+ if was_added {
+ self.stats += measurement;
+ }
+
+ Ok(was_added)
+ }
+
+ fn merge(&mut self, key: EntryHash, value: ContextValue) -> Result<(), StorageBackendError> {
+ let mut w = self
+ .inner
+ .write()
+ .map_err(|e| StorageBackendError::GuardPoison {
+ error: format!("{}", e),
+ })?;
+
+ w.insert(key, value);
+ Ok(())
+ }
+
+ fn delete(&mut self, key: &EntryHash) -> Result<Option<ContextValue>, StorageBackendError> {
+ let mut w = self
+ .inner
+ .write()
+ .map_err(|e| StorageBackendError::GuardPoison {
+ error: format!("{}", e),
+ })?;
+
+ Ok(w.remove(key))
+ }
+
+ fn get(&self, key: &EntryHash) -> Result<Option<ContextValue>, StorageBackendError> {
+ let db = self.inner.clone();
+ let r = db.read().map_err(|e| StorageBackendError::GuardPoison {
+ error: format!("{}", e),
+ })?;
+
+ match r.get(key) {
+ None => Ok(None),
+ Some(v) => Ok(Some(v.clone())),
+ }
+ }
+
+ fn contains(&self, key: &EntryHash) -> Result<bool, StorageBackendError> {
+ let db = self.inner.clone();
+ let r = db.read().map_err(|e| StorageBackendError::GuardPoison {
+ error: format!("{}", e),
+ })?;
+ Ok(r.contains_key(key))
+ }
+
+ fn get_mem_use_stats(&self) -> Result<RocksDBStats, StorageBackendError> {
+ Ok(RocksDBStats {
+ mem_table_total: 0,
+ mem_table_unflushed: 0,
+ mem_table_readers_total: 0,
+ cache_total: 0,
+ })
+ }
+}

diff:
+pub mod btree_map;
+pub mod in_memory_backend;
+pub mod rocksdb_backend;
+pub mod sled_backend;
+
+pub use btree_map::*;
+pub use in_memory_backend::*;
+pub use rocksdb_backend::*;
+pub use sled_backend::*;

diff:
+use crate::merkle_storage::{ContextValue, EntryHash};
+use crate::persistent::database::KeyValueStoreWithSchema;
+use crate::persistent::database::RocksDBStats;
+use crate::storage_backend::{StorageBackend, StorageBackendError, StorageBackendStats};
+use rocksdb::{WriteOptions, DB};
+use serde::{Deserialize, Serialize};
+use std::collections::HashSet;
+use std::sync::Arc;
+
+pub struct RocksDBBackend {
+ column_name: &'static str,
+ inner: Arc<DB>,
+}
+
+impl RocksDBBackend {
+ pub fn new(db: Arc<DB>, column_name: &'static str) -> Self {
+ RocksDBBackend {
+ inner: db,
+ column_name,
+ }
+ }
+}
+
+impl RocksDBBackend {
+ fn default_write_options() -> WriteOptions {
+ let mut opts = WriteOptions::default();
+ opts.set_sync(false);
+ opts
+ }
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct RocksDBBackendStats {
+ mem_table_total: u64,
+ mem_table_unflushed: u64,
+ mem_table_readers_total: u64,
+ cache_total: u64,
+}
+
+impl StorageBackend for RocksDBBackend {
+ fn is_persisted(&self) -> bool {
+ true
+ }
+
+ fn put(&mut self, key: EntryHash, value: ContextValue) -> Result<bool, StorageBackendError> {
+ let cf = self.inner.cf_handle(&self.column_name).ok_or(
+ StorageBackendError::MissingColumnFamily {
+ name: &self.column_name,
+ },
+ )?;
+
+ self.inner
+ .put_cf_opt(
+ cf,
+ &key.as_ref()[..],
+ &value,
+ &Self::default_write_options(),
+ )
+ .map_err(StorageBackendError::from)
+ .map(|_| true)
+ }
+
+ fn merge(&mut self, key: EntryHash, value: ContextValue) -> Result<(), StorageBackendError> {
+ let cf = self.inner.cf_handle(&self.column_name).ok_or(
+ StorageBackendError::MissingColumnFamily {
+ name: &self.column_name,
+ },
+ )?;
+
+ self.inner
+ .merge_cf_opt(
+ cf,
+ &key.as_ref()[..],
+ &value,
+ &Self::default_write_options(),
+ )
+ .map_err(StorageBackendError::from)
+ }
+
+ /// Warning: always returns None.
+ fn delete(&mut self, key: &EntryHash) -> Result<Option<ContextValue>, StorageBackendError> {
+ let cf = self.inner.cf_handle(&self.column_name).ok_or(
+ StorageBackendError::MissingColumnFamily {
+ name: &self.column_name,
+ },
+ )?;
+
+ self.inner
+ .delete_cf_opt(cf, &key.as_ref()[..], &Self::default_write_options())
+ .map_err(StorageBackendError::from)?;
+ Ok(None)
+ }
+
+ fn get(&self, key: &EntryHash) -> Result<Option<ContextValue>, StorageBackendError> {
+ let cf = self.inner.cf_handle(&self.column_name).ok_or(
+ StorageBackendError::MissingColumnFamily {
+ name: &self.column_name,
+ },
+ )?;
+
+ let v = self
+ .inner
+ .get_cf(cf, &key.as_ref()[..])
+ .map_err(StorageBackendError::from)?
+ .map(|value| value);
+ Ok(v)
+ }
+
+ fn contains(&self, key: &EntryHash) -> Result<bool, StorageBackendError> {
+ self.get(key).map(|v| v.is_some())
+ }
+
+ fn get_mem_use_stats(&self) -> Result<RocksDBStats, StorageBackendError> {
+ // TODO - fix compilation problem
+ // let r = self.inner.get_mem_use_stats();
+ return Err(StorageBackendError::BackendError);
+ }
+}

diff:
+use crate::merkle_storage::{ContextValue, EntryHash};
+use crate::persistent::database::RocksDBStats;
+use crate::storage_backend::{StorageBackend, StorageBackendError, StorageBackendStats};
+
+pub struct SledBackend {
+ inner: sled::Tree,
+}
+
+impl SledBackend {
+ pub fn new(db: sled::Tree) -> Self {
+ SledBackend { inner: db }
+ }
+}
+
+impl StorageBackend for SledBackend {
+ fn is_persisted(&self) -> bool {
+ true
+ }
+
+ fn put(&mut self, key: EntryHash, value: ContextValue) -> Result<bool, StorageBackendError> {
+ Ok(self
+ .inner
+ .insert(&key.as_ref()[..], value)
+ .map(|v| v.is_none())?)
+ }
+
+ fn merge(&mut self, key: EntryHash, value: ContextValue) -> Result<(), StorageBackendError> {
+ self.inner.insert(&key.as_ref()[..], value)?;
+ Ok(())
+ }
+
+ fn delete(&mut self, key: &EntryHash) -> Result<Option<ContextValue>, StorageBackendError> {
+ Ok(self.inner.remove(&key.as_ref()[..])?.map(|v| v.to_vec()))
+ }
+
+ fn get(&self, key: &EntryHash) -> Result<Option<ContextValue>, StorageBackendError> {
+ let r = self.inner.get(&key.as_ref()[..])?;
+
+ match r {
+ None => Err(StorageBackendError::BackendError),
+ Some(v) => Ok(Some(v.to_vec())),
+ }
+ }
+
+ fn contains(&self, key: &EntryHash) -> Result<bool, StorageBackendError> {
+ Ok(self.inner.contains_key(&key.as_ref()[..])?)
+ }
+
+ fn get_mem_use_stats(&self) -> Result<RocksDBStats, StorageBackendError> {
+ Ok(RocksDBStats {
+ mem_table_total: 0,
+ mem_table_unflushed: 0,
+ mem_table_readers_total: 0,
+ cache_total: 0,
+ })
+ }
+}

diff:
// SPDX-License-Identifier: MIT
#![forbid(unsafe_code)]
#![feature(const_fn)]
+#![feature(allocator_api)]
use std::convert::{TryFrom, TryInto};
use std::path::Path;
-use std::sync::Arc;
+use std::sync::{Arc, RwLock};
use failure::Fail;
use rocksdb::Cache;
@@ -24,6 +25,7 @@ use tezos_messages::p2p::binary_message::{BinaryMessage, MessageHash, MessageHas
use tezos_messages::p2p::encoding::prelude::BlockHeader;
use tezos_messages::Head;
+use crate::backend::RocksDBBackend;
pub use crate::block_meta_storage::{BlockMetaStorage, BlockMetaStorageKV, BlockMetaStorageReader};
pub use crate::block_storage::{
BlockAdditionalData, BlockAdditionalDataBuilder, BlockJsonData, BlockJsonDataBuilder,
@@ -49,6 +51,7 @@ pub use action_file_storage::ActionFileStorage;
pub mod action_file;
pub mod action_file_storage;
+pub mod backend;
pub mod block_meta_storage;
pub mod block_storage;
pub mod chain_meta_storage;
@@ -61,6 +64,7 @@ pub mod operations_storage;
pub mod persistent;
pub mod predecessor_storage;
pub mod skip_list;
+pub mod storage_backend;
pub mod system_storage;
/// Extension of block header with block hash
@@ -466,6 +470,14 @@ pub fn check_database_compatibility(
Ok(db_version_ok && chain_id_ok)
}
+#[derive(PartialEq, Debug, Clone)]
+pub enum KeyValueStoreBackend {
+ RocksDB,
+ InMem,
+ Sled,
+ BTreeMap,
+}
+
pub mod tests_common {
use std::path::{Path, PathBuf};
use std::sync::Arc;
@@ -560,6 +572,7 @@ pub mod tests_common {
Arc::new(kv_context),
Arc::new(kv_context_action),
Arc::new(clog),
+ KeyValueStoreBackend::RocksDB,
),
path,
remove_on_destroy,

diff:
@@ -49,11 +49,12 @@ use std::convert::TryInto;
use std::hash::Hash;
use std::sync::Arc;
use std::time::Instant;
+use std::ops::Deref;
use blake2::digest::{Update, VariableOutput};
use blake2::VarBlake2b;
use failure::Fail;
-use rocksdb::{Cache, ColumnFamilyDescriptor, WriteBatch};
+use rocksdb::{Cache, ColumnFamilyDescriptor};
use serde::Deserialize;
use serde::Serialize;
@@ -63,6 +64,7 @@ use crate::persistent;
use crate::persistent::database::RocksDBStats;
use crate::persistent::BincodeEncoded;
use crate::persistent::{default_table_options, KeyValueSchema, KeyValueStoreWithSchema};
+use crate::storage_backend::{StorageBackend, StorageBackendError};
const HASH_LEN: usize = 32;
@@ -126,7 +128,7 @@ enum Action {
Remove(RemoveAction),
}
-pub type MerkleStorageKV = dyn KeyValueStoreWithSchema<MerkleStorage> + Sync + Send;
+pub type MerkleStorageKV = dyn StorageBackend + Sync + Send;
pub type RefCnt = usize;
@@ -134,7 +136,7 @@ pub struct MerkleStorage {
/// tree with current staging area (currently checked out context)
current_stage_tree: Option<Tree>,
current_stage_tree_hash: Option<EntryHash>,
- db: Arc<MerkleStorageKV>,
+ db: Box<MerkleStorageKV>,
/// all entries in current staging area
staged: Vec<(EntryHash, RefCnt, Entry)>,
/// HashMap for looking up entry index in self.staged by hash
@@ -153,8 +155,12 @@ pub enum MerkleError {
DBError {
error: persistent::database::DBError,
},
+ #[fail(display = "KVStore error: {:?}", error)]
+ KVBackendError { error: StorageBackendError },
#[fail(display = "Serialization error: {:?}", error)]
SerializationError { error: bincode::Error },
+ #[fail(display = "Backend error: {:?}", error)]
+ StorageBackendError { error: StorageBackendError },
/// Internal unrecoverable bugs that should never occur
#[fail(display = "No root retrieved for this commit!")]
@@ -187,9 +193,9 @@ pub enum MerkleError {
HashError { error: FromBytesError },
}
-impl From<persistent::database::DBError> for MerkleError {
- fn from(error: persistent::database::DBError) -> Self {
- MerkleError::DBError { error }
+impl From<StorageBackendError> for MerkleError {
+ fn from(error: StorageBackendError) -> Self {
+ MerkleError::StorageBackendError { error }
}
}
@@ -355,7 +361,7 @@ fn hash_commit(commit: &Commit) -> Result<EntryHash, MerkleError> {
}
impl MerkleStorage {
- pub fn new(db: Arc<MerkleStorageKV>) -> Self {
+ pub fn new(db: Box<MerkleStorageKV>) -> Self {
MerkleStorage {
db,
staged: Vec::new(),
@@ -371,6 +377,10 @@ impl MerkleStorage {
}
}
+ pub fn has_persistent_backend(&self) -> bool {
+ self.db.is_persisted()
+ }
+
/// Get value from current staged root
pub fn get(&mut self, key: &ContextKey) -> Result<ContextValue, MerkleError> {
let instant = Instant::now();
@@ -1147,14 +1157,16 @@ impl MerkleStorage {
}
/// Persists an entry and its descendants from staged area to database on disk.
- fn persist_staged_entry_to_db(&self, entry: &Entry) -> Result<(), MerkleError> {
- let mut batch = WriteBatch::default(); // batch containing DB key values to persist
+ fn persist_staged_entry_to_db(&mut self, entry: &Entry) -> Result<(), MerkleError> {
+ let mut batch: Vec<(EntryHash, ContextValue)> = Vec::new();
// build list of entries to be persisted
self.get_entries_recursively(entry, &mut batch)?;
// atomically write all entries in one batch to DB
- self.db.write_batch(batch)?;
+ for (k, v) in batch {
+ self.db.put(k, v)?;
+ }
Ok(())
}
@@ -1163,11 +1175,11 @@ impl MerkleStorage {
fn get_entries_recursively(
&self,
entry: &Entry,
- batch: &mut WriteBatch,
+ batch: &mut Vec<(EntryHash, ContextValue)>,
) -> Result<(), MerkleError> {
// add entry to batch
- self.db
- .put_batch(batch, &self.hash_entry(entry)?, &bincode::serialize(entry)?)?;
+ // self.db.put(self.hash_entry(entry)?, bincode::serialize(entry)?)?;
+ batch.push((self.hash_entry(entry)?, bincode::serialize(entry)?));
match entry {
Entry::Blob(_) => Ok(()),
@@ -1407,6 +1419,7 @@ impl MerkleStorage {
#[allow(unused_must_use)]
mod tests {
// use hex;
+ use crate::backend::{BTreeMapBackend, InMemoryBackend, RocksDBBackend, SledBackend};
use assert_json_diff::assert_json_eq;
use rocksdb::{Options, DB};
use std::path::{Path, PathBuf};
@@ -1436,8 +1449,23 @@ mod tests {
open_db(get_db_name(db_name), &cache)
}
- fn get_storage(dn_name: &str, cache: &Cache) -> MerkleStorage {
- MerkleStorage::new(Arc::new(get_db(dn_name, &cache)))
+ fn get_storage(db_name: &str, cache: &Cache) -> MerkleStorage {
+ let default_backend = "rocksdb".to_string();
+ let backend = env::var("KVBACKEND").unwrap_or(default_backend);
+ let sled = sled::Config::new().path(db_name).open().unwrap();
+
+ match backend.as_str() {
+ "rocksdb" => MerkleStorage::new(Box::new(RocksDBBackend::new(
+ Arc::new(get_db(db_name, &cache)),
+ MerkleStorage::name(),
+ ))),
+ "sled" => MerkleStorage::new(Box::new(SledBackend::new(sled.deref().clone()))),
+ "btree" => MerkleStorage::new(Box::new(BTreeMapBackend::new())),
+ "inmem" => MerkleStorage::new(Box::new(InMemoryBackend::new())),
+ _ => {
+ panic!("unknown backend set")
+ }
+ }
}
fn clean_db(db_name: &str) {
@@ -1832,6 +1860,9 @@ mod tests {
let cache = Cache::new_lru_cache(32 * 1024 * 1024).unwrap();
let mut storage = get_storage(db_name, &cache);
+ if !storage.has_persistent_backend() {
+ return;
+ }
assert_eq!(
storage.get_history(&commit1, key_abc).unwrap(),
@@ -1987,6 +2018,9 @@ mod tests {
let cache = Cache::new_lru_cache(32 * 1024 * 1024).unwrap();
let mut storage = get_storage(db_name, &cache);
+ if !storage.has_persistent_backend() {
+ return;
+ }
storage.checkout(&commit1);
assert_eq!(storage.get(&key_abc).unwrap(), vec![1u8]);
assert_eq!(storage.get(&key_abx).unwrap(), vec![2u8]);
@@ -2018,6 +2052,9 @@ mod tests {
let cache = Cache::new_lru_cache(32 * 1024 * 1024).unwrap();
let mut storage = get_storage(db_name, &cache);
+ if !storage.has_persistent_backend() {
+ return;
+ }
assert_eq!(vec![2_u8], storage.get_history(&commit1, &key_abc).unwrap());
}
@@ -2028,15 +2065,25 @@ mod tests {
{
clean_db(db_name);
let cache = Cache::new_lru_cache(32 * 1024 * 1024).unwrap();
- get_storage(db_name, &cache);
+ MerkleStorage::new(Box::new(RocksDBBackend::new(
+ Arc::new(get_db(db_name, &cache)),
+ MerkleStorage::name(),
+ )));
}
let db = DB::open_for_read_only(&Options::default(), get_db_name(db_name), true).unwrap();
- let mut storage = MerkleStorage::new(Arc::new(db));
+ let mut storage = MerkleStorage::new(Box::new(RocksDBBackend::new(
+ Arc::new(db),
+ MerkleStorage::name(),
+ )));
storage.set(&vec!["a".to_string()], &vec![1u8]);
let res = storage.commit(0, "".to_string(), "".to_string());
+ println!("{:?}", res);
- assert!(matches!(res.err().unwrap(), MerkleError::DBError { .. }));
+ assert!(matches!(
+ res.err().unwrap(),
+ MerkleError::StorageBackendError { .. }
+ ));
}
// Test getting entire tree in string format for JSON RPC

diff:
@@ -12,10 +12,10 @@ use crate::persistent::schema::KeyValueSchema;
#[derive(Serialize, Debug, Clone)]
pub struct RocksDBStats {
- mem_table_total: u64,
- mem_table_unflushed: u64,
- mem_table_readers_total: u64,
- cache_total: u64,
+ pub mem_table_total: u64,
+ pub mem_table_unflushed: u64,
+ pub mem_table_readers_total: u64,
+ pub cache_total: u64,
}
/// Possible errors for schema

diff:
// SPDX-License-Identifier: MIT
use failure::Fail;
+use std::ops::Deref;
use std::path::Path;
use std::sync::{Arc, RwLock};
use crate::action_file::ActionFileError;
+use crate::KeyValueStoreBackend;
use crate::StorageError;
use derive_builder::Builder;
use rocksdb::{BlockBasedOptions, Cache, ColumnFamilyDescriptor, Options, DB};
@@ -15,6 +17,10 @@ pub use commit_log::{CommitLogError, CommitLogRef, CommitLogWithSchema, CommitLo
pub use database::{DBError, KeyValueStoreWithSchema};
pub use schema::{CommitLogDescriptor, CommitLogSchema, KeyValueSchema};
+use crate::backend::btree_map::BTreeMapBackend;
+use crate::backend::in_memory_backend::InMemoryBackend;
+use crate::backend::rocksdb_backend::RocksDBBackend;
+use crate::backend::sled_backend::SledBackend;
use crate::merkle_storage::MerkleStorage;
use crate::persistent::sequence::Sequences;
use tezos_context::channel::ContextActionMessage;
@@ -145,7 +151,22 @@ impl PersistentStorage {
db_context: Arc<DB>,
db_context_actions: Arc<DB>,
clog: Arc<CommitLogs>,
+ merkle_backend: KeyValueStoreBackend,
) -> Self {
+ let sled = sled::Config::new().path("/tmp/sled").open().unwrap();
+
+ let merkle = match merkle_backend {
+ KeyValueStoreBackend::RocksDB => MerkleStorage::new(Box::new(RocksDBBackend::new(
+ db_context.clone(),
+ MerkleStorage::name(),
+ ))),
+ KeyValueStoreBackend::InMem => MerkleStorage::new(Box::new(InMemoryBackend::new())),
+ KeyValueStoreBackend::Sled => {
+ MerkleStorage::new(Box::new(SledBackend::new(sled.deref().clone())))
+ }
+ KeyValueStoreBackend::BTreeMap => MerkleStorage::new(Box::new(BTreeMapBackend::new())),
+ };
+
let seq = Arc::new(Sequences::new(db.clone(), 1000));
Self {
clog,
@@ -153,7 +174,7 @@ impl PersistentStorage {
db_context: db_context.clone(),
db_context_actions,
seq,
- merkle: Arc::new(RwLock::new(MerkleStorage::new(db_context))),
+ merkle: Arc::new(RwLock::new(merkle)),
}
}

diff:
+use crate::persistent::database::{DBError, RocksDBStats};
+use failure::Fail;
+use serde::Serialize;
+use std::collections::HashSet;
+use std::mem;
+
+use crate::merkle_storage::{ContextValue, EntryHash};
+
+pub fn size_of_vec<T>(v: &Vec<T>) -> usize {
+ mem::size_of::<Vec<T>>() + mem::size_of::<T>() * v.capacity()
+}
+
+#[derive(Debug, Fail)]
+pub enum StorageBackendError {
+ #[fail(display = "RocksDB error: {}", error)]
+ RocksDBError { error: rocksdb::Error },
+ #[fail(display = "Column family {} is missing", name)]
+ MissingColumnFamily { name: &'static str },
+ #[fail(display = "Backend Error")]
+ BackendError,
+ #[fail(display = "SledDB error: {}", error)]
+ SledDBError { error: sled::Error },
+ #[fail(display = "Guard Poison {} ", error)]
+ GuardPoison { error: String },
+ #[fail(display = "Serialization error: {:?}", error)]
+ SerializationError { error: bincode::Error },
+ #[fail(display = "DBError error: {:?}", error)]
+ DBError { error: DBError },
+}
+
+impl From<rocksdb::Error> for StorageBackendError {
+ fn from(error: rocksdb::Error) -> Self {
+ StorageBackendError::RocksDBError { error }
+ }
+}
+
+impl From<sled::Error> for StorageBackendError {
+ fn from(error: sled::Error) -> Self {
+ StorageBackendError::SledDBError { error }
+ }
+}
+
+impl From<DBError> for StorageBackendError {
+ fn from(error: DBError) -> Self {
+ StorageBackendError::DBError { error }
+ }
+}
+
+impl From<bincode::Error> for StorageBackendError {
+ fn from(error: bincode::Error) -> Self {
+ StorageBackendError::SerializationError { error }
+ }
+}
+
+impl slog::Value for StorageBackendError {
+ fn serialize(
+ &self,
+ _record: &slog::Record,
+ key: slog::Key,
+ serializer: &mut dyn slog::Serializer,
+ ) -> slog::Result {
+ serializer.emit_arguments(key, &format_args!("{}", self))
+ }
+}
+
+pub trait StorageBackend: Send + Sync {
+ fn is_persisted(&self) -> bool;
+ fn get(&self, key: &EntryHash) -> Result<Option<ContextValue>, StorageBackendError>;
+ fn put(&mut self, key: EntryHash, value: ContextValue) -> Result<bool, StorageBackendError>;
+ fn merge(&mut self, key: EntryHash, value: ContextValue) -> Result<(), StorageBackendError>;
+ fn delete(&mut self, key: &EntryHash) -> Result<Option<ContextValue>, StorageBackendError>;
+ fn contains(&self, key: &EntryHash) -> Result<bool, StorageBackendError>;
+ fn get_mem_use_stats(&self) -> Result<RocksDBStats, StorageBackendError>;
+}
+
+#[derive(Debug, Default, Clone, Copy, Serialize)]
+pub struct StorageBackendStats {
+ pub key_bytes: usize,
+ pub value_bytes: usize,
+ pub reused_keys_bytes: usize,
+}
+
+impl StorageBackendStats {
+ /// increases `reused_keys_bytes` based on `key`
+ pub fn update_reused_keys(&mut self, list: &HashSet<EntryHash>) {
+ // TODO: bring back when MerklHash aka EntryHash will be allocated
+ // on stack
+ // self.reused_keys_bytes = list.capacity() * mem::size_of::<EntryHash>();
+ self.reused_keys_bytes = list.capacity() * 32;
+ }
+
+ pub fn total_as_bytes(&self) -> usize {
+ self.key_bytes + self.value_bytes + self.reused_keys_bytes
+ }
+}
+
+impl<'a> std::ops::Add<&'a Self> for StorageBackendStats {
+ type Output = Self;
+
+ fn add(self, other: &'a Self) -> Self::Output {
+ Self {
+ key_bytes: self.key_bytes + other.key_bytes,
+ value_bytes: self.value_bytes + other.value_bytes,
+ reused_keys_bytes: self.reused_keys_bytes + other.reused_keys_bytes,
+ }
+ }
+}
+
+impl std::ops::Add for StorageBackendStats {
+ type Output = Self;
+
+ fn add(self, other: Self) -> Self::Output {
+ self + &other
+ }
+}
+
+impl<'a> std::ops::AddAssign<&'a Self> for StorageBackendStats {
+ fn add_assign(&mut self, other: &'a Self) {
+ *self = *self + other;
+ }
+}
+
+impl std::ops::AddAssign for StorageBackendStats {
+ fn add_assign(&mut self, other: Self) {
+ *self = *self + other;
+ }
+}
+
+impl<'a> std::ops::Sub<&'a Self> for StorageBackendStats {
+ type Output = Self;
+
+ fn sub(self, other: &'a Self) -> Self::Output {
+ Self {
+ key_bytes: self.key_bytes - other.key_bytes,
+ value_bytes: self.value_bytes - other.value_bytes,
+ reused_keys_bytes: self.reused_keys_bytes - other.reused_keys_bytes,
+ }
+ }
+}
+
+impl std::ops::Sub for StorageBackendStats {
+ type Output = Self;
+
+ fn sub(self, other: Self) -> Self::Output {
+ self - &other
+ }
+}
+
+impl<'a> std::ops::SubAssign<&'a Self> for StorageBackendStats {
+ fn sub_assign(&mut self, other: &'a Self) {
+ *self = *self - other;
+ }
+}
+
+impl std::ops::SubAssign for StorageBackendStats {
+ fn sub_assign(&mut self, other: Self) {
+ *self = *self - other;
+ }
+}
+
+impl<'a> std::iter::Sum<&'a StorageBackendStats> for StorageBackendStats {
+ fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
+ iter.fold(StorageBackendStats::default(), |acc, cur| acc + cur)
+ }
+}
+
+impl From<(&EntryHash, &ContextValue)> for StorageBackendStats {
+ fn from((entry_hash, value): (&EntryHash, &ContextValue)) -> Self {
+ StorageBackendStats {
+ // TODO: bring back when MerklHash aka EntryHash will be allocated
+ // on stack
+ // key_bytes: mem::size_of::<EntryHash>(),
+ key_bytes: entry_hash.as_ref().len(),
+ value_bytes: size_of_vec(&value),
+ reused_keys_bytes: 0,
+ }
+ }
+}

license: MIT License

repo: tezedge/tezedge


message: fixing merge & put signatures

diff:
@@ -484,6 +484,11 @@ pub fn tezos_app() -> App<'static, 'static> {
.multiple(true)
.value_name("STRING")
.help("Activate recording of context storage actions"))
+ .arg(Arg::with_name("kv-store-backend")
+ .long("kv-store-backend")
+ .takes_value(true)
+ .value_name("STRING")
+ .help("Choose the merkle storege backend - supported backends: 'rocksdb', 'sled', 'inmem', 'btree'"))
.arg(Arg::with_name("compute-context-action-tree-hashes")
.long("compute-context-action-tree-hashes")
.takes_value(true)

diff:
@@ -36,8 +36,8 @@ impl KVStoreTrait for KVStore<EntryHash, ContextValue> {
}
/// put kv in map if key doesn't exist. If it does then return false.
- fn put(&mut self, key: EntryHash, value: ContextValue) -> Result<bool, KVStoreError> {
- match self.kv_map.entry(key) {
+ fn put(&mut self, key: &EntryHash, value: ContextValue) -> Result<bool, KVStoreError> {
+ match self.kv_map.entry(key.clone()) {
Entry::Vacant(entry) => {
entry.insert(value);
Ok(true)
@@ -46,8 +46,8 @@ impl KVStoreTrait for KVStore<EntryHash, ContextValue> {
}
}
- fn merge(&mut self, key: EntryHash, value: ContextValue) -> Result<(), KVStoreError> {
- self.kv_map.insert(key, value);
+ fn merge(&mut self, key: &EntryHash, value: ContextValue) -> Result<(), KVStoreError> {
+ self.kv_map.insert(key.clone(), value);
Ok(())
}

diff:
@@ -28,8 +28,8 @@ impl StorageBackend for InMemoryBackend {
false
}
- fn put(&mut self, key: EntryHash, value: ContextValue) -> Result<bool, StorageBackendError> {
- let measurement = StorageBackendStats::from((&key, &value));
+ fn put(&mut self, key: &EntryHash, value: ContextValue) -> Result<bool, StorageBackendError> {
+ let measurement = StorageBackendStats::from((key, &value));
let mut w = self
.inner
.write()
@@ -37,7 +37,7 @@ impl StorageBackend for InMemoryBackend {
error: format!("{}", e),
})?;
- let was_added = w.insert(key, value).is_none();
+ let was_added = w.insert(key.clone(), value).is_none();
if was_added {
self.stats += measurement;
@@ -46,7 +46,7 @@ impl StorageBackend for InMemoryBackend {
Ok(was_added)
}
- fn merge(&mut self, key: EntryHash, value: ContextValue) -> Result<(), StorageBackendError> {
+ fn merge(&mut self, key: &EntryHash, value: ContextValue) -> Result<(), StorageBackendError> {
let mut w = self
.inner
.write()
@@ -54,7 +54,7 @@ impl StorageBackend for InMemoryBackend {
error: format!("{}", e),
})?;
- w.insert(key, value);
+ w.insert(key.clone(), value);
Ok(())
}

diff:
@@ -45,7 +45,7 @@ impl StorageBackend for RocksDBBackend {
true
}
- fn put(&mut self, key: EntryHash, value: ContextValue) -> Result<bool, StorageBackendError> {
+ fn put(&mut self, key: &EntryHash, value: ContextValue) -> Result<bool, StorageBackendError> {
let cf = self.inner.cf_handle(&self.column_name).ok_or(
StorageBackendError::MissingColumnFamily {
name: &self.column_name,
@@ -63,7 +63,7 @@ impl StorageBackend for RocksDBBackend {
.map(|_| true)
}
- fn merge(&mut self, key: EntryHash, value: ContextValue) -> Result<(), StorageBackendError> {
+ fn merge(&mut self, key: &EntryHash, value: ContextValue) -> Result<(), StorageBackendError> {
let cf = self.inner.cf_handle(&self.column_name).ok_or(
StorageBackendError::MissingColumnFamily {
name: &self.column_name,

diff:
@@ -20,14 +20,14 @@ impl StorageBackend for SledBackend {
true
}
- fn put(&mut self, key: EntryHash, value: ContextValue) -> Result<bool, StorageBackendError> {
+ fn put(&mut self, key: &EntryHash, value: ContextValue) -> Result<bool, StorageBackendError> {
Ok(self
.inner
.insert(&key.as_ref()[..], value)
.map(|v| v.is_none())?)
}
- fn merge(&mut self, key: EntryHash, value: ContextValue) -> Result<(), StorageBackendError> {
+ fn merge(&mut self, key: &EntryHash, value: ContextValue) -> Result<(), StorageBackendError> {
self.inner.insert(&key.as_ref()[..], value)?;
Ok(())
}

diff:
@@ -1164,7 +1164,7 @@ impl MerkleStorage {
// atomically write all entries in one batch to DB
for (k, v) in batch {
- self.db.put(k, v)?;
+ self.db.put(&k, v)?;
}
Ok(())

diff:
@@ -153,8 +153,6 @@ impl PersistentStorage {
clog: Arc<CommitLogs>,
merkle_backend: KeyValueStoreBackend,
) -> Self {
- let sled = sled::Config::new().path("/tmp/sled").open().unwrap();
-
let merkle = match merkle_backend {
KeyValueStoreBackend::RocksDB => MerkleStorage::new(Box::new(RocksDBBackend::new(
db_context.clone(),
@@ -162,6 +160,7 @@ impl PersistentStorage {
))),
KeyValueStoreBackend::InMem => MerkleStorage::new(Box::new(InMemoryBackend::new())),
KeyValueStoreBackend::Sled => {
+ let sled = sled::Config::new().temporary(true).open().unwrap();
MerkleStorage::new(Box::new(SledBackend::new(sled.deref().clone())))
}
KeyValueStoreBackend::BTreeMap => MerkleStorage::new(Box::new(BTreeMapBackend::new())),

diff:
@@ -69,8 +69,8 @@ impl slog::Value for StorageBackendError {
pub trait StorageBackend: Send + Sync {
fn is_persisted(&self) -> bool;
fn get(&self, key: &EntryHash) -> Result<Option<ContextValue>, StorageBackendError>;
- fn put(&mut self, key: EntryHash, value: ContextValue) -> Result<bool, StorageBackendError>;
- fn merge(&mut self, key: EntryHash, value: ContextValue) -> Result<(), StorageBackendError>;
+ fn put(&mut self, key: &EntryHash, value: ContextValue) -> Result<bool, StorageBackendError>;
+ fn merge(&mut self, key: &EntryHash, value: ContextValue) -> Result<(), StorageBackendError>;
fn delete(&mut self, key: &EntryHash) -> Result<Option<ContextValue>, StorageBackendError>;
fn contains(&self, key: &EntryHash) -> Result<bool, StorageBackendError>;
fn get_mem_use_stats(&self) -> Result<RocksDBStats, StorageBackendError>;

original_message: fixing merge & put signatures


message: temporarly unblock drone tests

diff:
// Copyright (c) SimpleStaking and Tezedge Contributors
// SPDX-License-Identifier: MIT
-use std::collections::{btree_map::Entry, BTreeMap, HashSet};
+use std::collections::{btree_map::Entry, BTreeMap};
use crate::merkle_storage::{ContextValue, EntryHash};
use crate::persistent::database::RocksDBStats;
use crate::storage_backend::{
StorageBackend as KVStoreTrait, StorageBackendError as KVStoreError,
- StorageBackendStats as KVStoreStats,
};
/// In Memory Key Value Store implemented with [BTreeMap](std::collections::BTreeMap)

diff:
// SPDX-License-Identifier: MIT
use crate::merkle_storage::{ContextValue, EntryHash};
-use crate::persistent::database::KeyValueStoreWithSchema;
use crate::persistent::database::RocksDBStats;
-use crate::storage_backend::{StorageBackend, StorageBackendError, StorageBackendStats};
+use crate::storage_backend::{StorageBackend, StorageBackendError};
use rocksdb::{WriteOptions, DB};
use serde::{Deserialize, Serialize};
-use std::collections::HashSet;
use std::sync::Arc;
pub struct RocksDBBackend {
@@ -116,6 +114,12 @@ impl StorageBackend for RocksDBBackend {
fn get_mem_use_stats(&self) -> Result<RocksDBStats, StorageBackendError> {
// TODO - fix compilation problem
//let r = self.inner.get_mem_use_stats();
- return Err(StorageBackendError::BackendError);
+ Ok(RocksDBStats {
+ mem_table_total: 0,
+ mem_table_unflushed: 0,
+ mem_table_readers_total: 0,
+ cache_total: 0,
+ })
+
}
}

diff:
@@ -62,7 +62,7 @@ use crypto::hash::{FromBytesError, HashType};
use crate::persistent;
use crate::persistent::database::RocksDBStats;
use crate::persistent::BincodeEncoded;
-use crate::persistent::{default_table_options, KeyValueSchema, KeyValueStoreWithSchema};
+use crate::persistent::{default_table_options, KeyValueSchema};
use crate::storage_backend::{StorageBackend, StorageBackendError};
const HASH_LEN: usize = 32;
@@ -453,7 +453,7 @@ impl MerkleStorage {
}
fn value_exists(&self, root_hash: &EntryHash, key: &ContextKey) -> Result<bool, MerkleError> {
- let mut full_path = key.clone();
+ let mut full_path = key.to_vec();
let file = full_path.pop().ok_or(MerkleError::KeyEmpty)?;
let path = full_path;
// find tree by path
@@ -491,7 +491,7 @@ impl MerkleStorage {
root_hash: &EntryHash,
key: &ContextKey,
) -> Result<ContextValue, MerkleError> {
- let mut full_path = key.clone();
+ let mut full_path = key.to_vec();
let file = full_path.pop().ok_or(MerkleError::KeyEmpty)?;
let path = full_path;
// find tree by path

original_message: temporarly unblock drone tests


message: dedicated trait for stats

diff:
@@ -35,7 +35,6 @@ use storage::persistent::{
};
use storage::ActionFileStorage;
use storage::ContextActionStorage;
-use storage::KeyValueStoreBackend;
use storage::{
check_database_compatibility, context::TezedgeContext, persistent::DBError,
resolve_storage_init_chain_data, BlockStorage, StorageInitInfo,

diff:
@@ -5,9 +5,7 @@ use std::collections::{btree_map::Entry, BTreeMap};
use crate::merkle_storage::{ContextValue, EntryHash};
use crate::persistent::database::RocksDBStats;
-use crate::storage_backend::{
- StorageBackend as KVStoreTrait, StorageBackendError as KVStoreError,
-};
+use crate::storage_backend::{StorageBackend as KVStoreTrait, StorageBackendError as KVStoreError};
/// In Memory Key Value Store implemented with [BTreeMap](std::collections::BTreeMap)
#[derive(Debug)]

diff:
// SPDX-License-Identifier: MIT
use crate::merkle_storage::{ContextValue, EntryHash};
+use crate::persistent::database::GetInMemStats;
use crate::persistent::database::RocksDBStats;
use crate::storage_backend::{StorageBackend, StorageBackendError};
use rocksdb::{WriteOptions, DB};
@@ -102,8 +103,7 @@ impl StorageBackend for RocksDBBackend {
let v = self
.inner
.get_cf(cf, &key.as_ref()[..])
- .map_err(StorageBackendError::from)?
- .map(|value| value);
+ .map_err(StorageBackendError::from)?;
Ok(v)
}
@@ -112,14 +112,8 @@ impl StorageBackend for RocksDBBackend {
}
fn get_mem_use_stats(&self) -> Result<RocksDBStats, StorageBackendError> {
- // TODO - fix compilation problem
- //let r = self.inner.get_mem_use_stats();
- Ok(RocksDBStats {
- mem_table_total: 0,
- mem_table_unflushed: 0,
- mem_table_readers_total: 0,
- cache_total: 0,
- })
-
+ self.inner
+ .get_stats()
+ .map_err(|_| StorageBackendError::BackendError)
}
}

diff:
@@ -123,6 +123,22 @@ pub trait KeyValueStoreWithSchema<S: KeyValueSchema> {
fn get_mem_use_stats(&self) -> Result<RocksDBStats, DBError>;
}
+pub trait GetInMemStats {
+ fn get_stats(&self) -> Result<RocksDBStats, DBError>;
+}
+
+impl GetInMemStats for DB {
+ fn get_stats(&self) -> Result<RocksDBStats, DBError> {
+ let memory_usage_stats = rocksdb::perf::get_memory_usage_stats(Some(&[&self]), None)?;
+ Ok(RocksDBStats {
+ mem_table_total: memory_usage_stats.mem_table_total,
+ mem_table_unflushed: memory_usage_stats.mem_table_unflushed,
+ mem_table_readers_total: memory_usage_stats.mem_table_readers_total,
+ cache_total: memory_usage_stats.cache_total,
+ })
+ }
+}
+
impl<S: KeyValueSchema> KeyValueStoreWithSchema<S> for DB {
fn put(&self, key: &S::Key, value: &S::Value) -> Result<(), DBError> {
let key = key.encode()?;

original_message: dedicated trait for stats


message: Addressing pr comments & clippy warnings

diff:
// Copyright (c) SimpleStaking and Tezedge Contributors
-// SPDX-License-Identifier: MIT/
+// SPDX-License-Identifier: MIT
pub mod btree_map;
pub mod in_memory_backend;

diff:
use crate::merkle_storage::{ContextValue, EntryHash};
use crate::persistent::database::RocksDBStats;
-use crate::storage_backend::{StorageBackend, StorageBackendError, StorageBackendStats};
+use crate::storage_backend::{StorageBackend, StorageBackendError};
pub struct SledBackend {
inner: sled::Tree,

diff:
use std::convert::{TryFrom, TryInto};
use std::path::Path;
-use std::sync::{Arc, RwLock};
+use std::sync::Arc;
use failure::Fail;
use rocksdb::Cache;
@@ -25,7 +25,6 @@ use tezos_messages::p2p::binary_message::{BinaryMessage, MessageHash, MessageHas
use tezos_messages::p2p::encoding::prelude::BlockHeader;
use tezos_messages::Head;
-use crate::backend::RocksDBBackend;
pub use crate::block_meta_storage::{BlockMetaStorage, BlockMetaStorageKV, BlockMetaStorageReader};
pub use crate::block_storage::{
BlockAdditionalData, BlockAdditionalDataBuilder, BlockJsonData, BlockJsonDataBuilder,


message: make use of atomic rocksdb write_batch functionality

diff:
@@ -43,6 +43,13 @@ impl KVStoreTrait for KVStore<EntryHash, ContextValue> {
}
}
+ fn put_batch(&mut self, batch: Vec<(EntryHash, ContextValue)>) -> Result<(), KVStoreError> {
+ for (k, v) in batch.into_iter() {
+ self.put(&k, v)?;
+ }
+ Ok(())
+ }
+
fn merge(&mut self, key: &EntryHash, value: ContextValue) -> Result<(), KVStoreError> {
self.kv_map.insert(key.clone(), value);
Ok(())

diff:
@@ -46,6 +46,16 @@ impl StorageBackend for InMemoryBackend {
Ok(was_added)
}
+ fn put_batch(
+ &mut self,
+ batch: Vec<(EntryHash, ContextValue)>,
+ ) -> Result<(), StorageBackendError> {
+ for (k, v) in batch.into_iter() {
+ self.put(&k, v)?;
+ }
+ Ok(())
+ }
+
fn merge(&mut self, key: &EntryHash, value: ContextValue) -> Result<(), StorageBackendError> {
let mut w = self
.inner

diff:
use crate::merkle_storage::{ContextValue, EntryHash};
use crate::persistent::database::GetInMemStats;
+use crate::persistent::database::KeyValueStoreWithSchema;
use crate::persistent::database::RocksDBStats;
use crate::storage_backend::{StorageBackend, StorageBackendError};
+use crate::MerkleStorage;
+use rocksdb::WriteBatch;
use rocksdb::{WriteOptions, DB};
use serde::{Deserialize, Serialize};
+use std::ops::Deref;
use std::sync::Arc;
pub struct RocksDBBackend {
@@ -62,6 +66,23 @@ impl StorageBackend for RocksDBBackend {
.map(|_| true)
}
+ fn put_batch(
+ &mut self,
+ batch: Vec<(EntryHash, ContextValue)>,
+ ) -> Result<(), StorageBackendError> {
+ let mut rocksb_batch = WriteBatch::default(); // batch containing DB key values to persist
+
+ for (k, v) in batch.iter() {
+ (self.inner.deref() as &dyn KeyValueStoreWithSchema<MerkleStorage>).put_batch(
+ &mut rocksb_batch,
+ &k,
+ &v,
+ )?;
+ }
+
+ Ok(())
+ }
+
fn merge(&mut self, key: &EntryHash, value: ContextValue) -> Result<(), StorageBackendError> {
let cf = self.inner.cf_handle(&self.column_name).ok_or(
StorageBackendError::MissingColumnFamily {

diff:
@@ -27,6 +27,16 @@ impl StorageBackend for SledBackend {
.map(|v| v.is_none())?)
}
+ fn put_batch(
+ &mut self,
+ batch: Vec<(EntryHash, ContextValue)>,
+ ) -> Result<(), StorageBackendError> {
+ for (k, v) in batch.into_iter() {
+ self.put(&k, v)?;
+ }
+ Ok(())
+ }
+
fn merge(&mut self, key: &EntryHash, value: ContextValue) -> Result<(), StorageBackendError> {
self.inner.insert(&key.as_ref()[..], value)?;
Ok(())

diff:
@@ -1162,10 +1162,8 @@ impl MerkleStorage {
// build list of entries to be persisted
self.get_entries_recursively(entry, &mut batch)?;
- // atomically write all entries in one batch to DB
- for (k, v) in batch {
- self.db.put(&k, v)?;
- }
+ // write all entries at once (depends on backend)
+ self.db.put_batch(batch)?;
Ok(())
}

diff:
@@ -70,6 +70,10 @@ pub trait StorageBackend: Send + Sync {
fn is_persisted(&self) -> bool;
fn get(&self, key: &EntryHash) -> Result<Option<ContextValue>, StorageBackendError>;
fn put(&mut self, key: &EntryHash, value: ContextValue) -> Result<bool, StorageBackendError>;
+ fn put_batch(
+ &mut self,
+ batch: Vec<(EntryHash, ContextValue)>,
+ ) -> Result<(), StorageBackendError>;
fn merge(&mut self, key: &EntryHash, value: ContextValue) -> Result<(), StorageBackendError>;
fn delete(&mut self, key: &EntryHash) -> Result<Option<ContextValue>, StorageBackendError>;
fn contains(&self, key: &EntryHash) -> Result<bool, StorageBackendError>;


message: add missing write_batch call

diff:
@@ -80,6 +80,10 @@ impl StorageBackend for RocksDBBackend {
)?;
}
+ (self.inner.deref() as &dyn KeyValueStoreWithSchema<MerkleStorage>).write_batch(
+ rocksb_batch,
+ )?;
+
Ok(())
}

original_message: add missing write_batch call


message:
add note about creating single abstraction for StorageBackend and KeyValueWithSchema
and about adding missing memory statistics for backends

diff:
@@ -68,6 +68,7 @@ impl KVStoreTrait for KVStore<EntryHash, ContextValue> {
}
fn get_mem_use_stats(&self) -> Result<RocksDBStats, KVStoreError> {
+ //TODO TE-431 StorageBackent::get_mem_use_stats() should be implemented for all backends
Ok(RocksDBStats {
mem_table_total: 0,
mem_table_unflushed: 0,

diff:
@@ -100,6 +100,7 @@ impl StorageBackend for InMemoryBackend {
}
fn get_mem_use_stats(&self) -> Result<RocksDBStats, StorageBackendError> {
+ //TODO TE-431 StorageBackent::get_mem_use_stats() should be implemented for all backends
Ok(RocksDBStats {
mem_table_total: 0,
mem_table_unflushed: 0,

diff:
@@ -80,9 +80,8 @@ impl StorageBackend for RocksDBBackend {
)?;
}
- (self.inner.deref() as &dyn KeyValueStoreWithSchema<MerkleStorage>).write_batch(
- rocksb_batch,
- )?;
+ (self.inner.deref() as &dyn KeyValueStoreWithSchema<MerkleStorage>)
+ .write_batch(rocksb_batch)?;
Ok(())
}

diff:
@@ -60,6 +60,7 @@ impl StorageBackend for SledBackend {
}
fn get_mem_use_stats(&self) -> Result<RocksDBStats, StorageBackendError> {
+ //TODO TE-431 StorageBackent::get_mem_use_stats() should be implemented for all backends
Ok(RocksDBStats {
mem_table_total: 0,
mem_table_unflushed: 0,

diff:
@@ -66,6 +66,7 @@ impl slog::Value for StorageBackendError {
}
}
+//TODO TE-432 - create single abstraction for StorageBackend and KeyValueWithSchema
pub trait StorageBackend: Send + Sync {
fn is_persisted(&self) -> bool;
fn get(&self, key: &EntryHash) -> Result<Option<ContextValue>, StorageBackendError>;


message: Record CHECKOUT actions and actions without `block_hash` too

diff:
@@ -20,6 +20,22 @@ use storage::{
use tezos_context::channel::ContextAction;
use tezos_messages::p2p::encoding::prelude::BlockHeaderBuilder;
+pub fn get_tree_action(action: &ContextAction) -> String {
+ match action {
+ ContextAction::Get { .. } => "ContextAction::Get".to_string(),
+ ContextAction::Mem { .. } => "ContextAction::Mem".to_string(),
+ ContextAction::DirMem { .. } => "ContextAction::DirMem".to_string(),
+ ContextAction::Set { .. } => "ContextAction::Set".to_string(),
+ ContextAction::Copy { .. } => "ContextAction::Copy".to_string(),
+ ContextAction::Delete { .. } => "ContextAction::Delete".to_string(),
+ ContextAction::RemoveRecursively { .. } => "ContextAction::RemoveRecursively".to_string(),
+ ContextAction::Commit { .. } => "ContextAction::Commit".to_string(),
+ ContextAction::Fold { .. } => "ContextAction::Fold".to_string(),
+ ContextAction::Checkout { .. } => "ContextAction::Checkout".to_string(),
+ ContextAction::Shutdown { .. } => "ContextAction::Shutdown".to_string(),
+ }
+}
+
fn create_logger() -> Logger {
let drain = slog_async::Async::new(
slog_term::FullFormat::new(slog_term::TermDecorator::new().build())
@@ -207,7 +223,7 @@ fn feed_tezedge_context_with_actions() -> Result<(), Error> {
| ContextAction::Commit { .. }
| ContextAction::Checkout { .. } => {
if let Err(e) = perform_context_action(&action, &mut context) {
- panic!("cannot perform action {:?} error: '{}'", &action, e);
+ panic!("cannot perform action error: '{}'", e);
}
}
ContextAction::Get { .. }
@@ -217,6 +233,14 @@ fn feed_tezedge_context_with_actions() -> Result<(), Error> {
| ContextAction::Shutdown { .. } => {}
};
+ // verify context hashes after each block
+ if let ContextAction::Checkout { context_hash, .. } = action {
+ assert_eq!(
+ context_hash.as_slice(),
+ context.get_last_commit_hash().unwrap().as_slice()
+ );
+ }
+
if let Some(expected_hash) = get_new_tree_hash(&action) {
assert_eq!(context.get_merkle_root(), expected_hash);
}

diff:
use crate::action_file::*;
use crate::persistent::{ActionRecordError, ActionRecorder};
use crate::StorageError;
-use crypto::hash::BlockHash;
-use std::collections::HashMap;
-use std::convert::TryFrom;
use std::path::PathBuf;
use tezos_context::channel::ContextAction;
pub struct ActionFileStorage {
file: PathBuf,
- staging: HashMap<BlockHash, Vec<ContextAction>>,
+ staging: Vec<ContextAction>,
level: u32,
}
@@ -20,89 +17,68 @@ impl ActionFileStorage {
pub fn new(path: PathBuf) -> Self {
ActionFileStorage {
file: path,
- staging: HashMap::new(),
+ staging: Vec::new(),
level: 0,
}
}
- fn store_single_action(&mut self, block_hash: BlockHash, action: &ContextAction) {
- let block_actions = self.staging.entry(block_hash).or_default();
- block_actions.push(action.clone());
+ fn store_single_action(&mut self, action: &ContextAction) {
+ self.staging.push(action.clone());
}
- fn store_commit_action(
- &mut self,
- block_hash: BlockHash,
- action: &ContextAction,
- ) -> Result<(), StorageError> {
+ fn store_commit_action(&mut self, action: &ContextAction) -> Result<(), StorageError> {
self.level += 1;
- self.store_single_action(block_hash.clone(), action);
- self.flush_entries_to_file(block_hash)
+ self.store_single_action(action);
+ self.flush_entries_to_file()
}
- fn flush_entries_to_file(&mut self, block_hash: BlockHash) -> Result<(), StorageError> {
+ fn flush_entries_to_file(&mut self) -> Result<(), StorageError> {
let mut action_file_writer =
ActionsFileWriter::new(&self.file).map_err(|e| StorageError::ActionRecordError {
error: ActionRecordError::ActionFileError { error: e },
})?;
- let actions =
- self.staging
- .remove(&block_hash)
- .ok_or(ActionRecordError::MissingActions {
- hash: block_hash.to_base58_check(),
- })?;
-
action_file_writer
- .update(actions)
+ .update(self.staging.clone())
.map_err(ActionRecordError::from)?;
+ self.staging.clear();
Ok(())
}
}
+pub fn get_tree_action(action: &ContextAction) -> String {
+ match action {
+ ContextAction::Get { .. } => "ContextAction::Get".to_string(),
+ ContextAction::Mem { .. } => "ContextAction::Mem".to_string(),
+ ContextAction::DirMem { .. } => "ContextAction::DirMem".to_string(),
+ ContextAction::Set { .. } => "ContextAction::Set".to_string(),
+ ContextAction::Copy { .. } => "ContextAction::Copy".to_string(),
+ ContextAction::Delete { .. } => "ContextAction::Delete".to_string(),
+ ContextAction::RemoveRecursively { .. } => "ContextAction::RemoveRecursively".to_string(),
+ ContextAction::Commit { .. } => "ContextAction::Commit".to_string(),
+ ContextAction::Fold { .. } => "ContextAction::Fold".to_string(),
+ ContextAction::Checkout { .. } => "ContextAction::Checkout".to_string(),
+ ContextAction::Shutdown { .. } => "ContextAction::Shutdown".to_string(),
+ }
+}
+
impl ActionRecorder for ActionFileStorage {
fn record(&mut self, context_action: &ContextAction) -> std::result::Result<(), StorageError> {
match context_action {
- ContextAction::Set {
- block_hash: Some(block_hash),
- ..
- }
- | ContextAction::Copy {
- block_hash: Some(block_hash),
- ..
- }
- | ContextAction::Delete {
- block_hash: Some(block_hash),
- ..
- }
- | ContextAction::RemoveRecursively {
- block_hash: Some(block_hash),
- ..
- }
- | ContextAction::Mem {
- block_hash: Some(block_hash),
- ..
- }
- | ContextAction::DirMem {
- block_hash: Some(block_hash),
- ..
- }
- | ContextAction::Get {
- block_hash: Some(block_hash),
- ..
- }
- | ContextAction::Fold {
- block_hash: Some(block_hash),
- ..
- } => {
- self.store_single_action(BlockHash::try_from(block_hash.clone())?, context_action);
+ ContextAction::Set { .. }
+ | ContextAction::Copy { .. }
+ | ContextAction::Delete { .. }
+ | ContextAction::RemoveRecursively { .. }
+ | ContextAction::Mem { .. }
+ | ContextAction::DirMem { .. }
+ | ContextAction::Get { .. }
+ | ContextAction::Checkout { .. }
+ | ContextAction::Fold { .. } => {
+ self.store_single_action(context_action);
Ok(())
}
- ContextAction::Commit {
- block_hash: Some(block_hash),
- ..
- } => self.store_commit_action(BlockHash::try_from(block_hash.clone())?, context_action),
- _ => Ok(()),
+ ContextAction::Commit { .. } => self.store_commit_action(context_action),
+ ContextAction::Shutdown => Ok(()),
}
}
}


message: use ContextAction::Checkout message for context hash validation in integration test

diff:
@@ -137,7 +137,9 @@ fn feed_tezedge_context_with_actions() -> Result<(), Error> {
let commit_log_db_path = PathBuf::from("/tmp/commit_log/");
let key_value_db_path = PathBuf::from("/tmp/key_value_store/");
- let input_file = env::var("INPUT").expect("test input not set");
+ let input_file = env::var("INPUT").expect("test input 'INPUT' not set");
+ let backend = env::var("BACKEND").expect("test backend 'BACKEND' not set");
+
let actions_storage_path = PathBuf::from(input_file.as_str());
let _ = fs::remove_dir_all(&commit_log_db_path);
@@ -151,7 +153,13 @@ fn feed_tezedge_context_with_actions() -> Result<(), Error> {
kv.clone(),
kv,
commit_log,
- storage::KeyValueStoreBackend::RocksDB, // TODO: test others too?
+ match backend.as_str() {
+ "inmem" => storage::KeyValueStoreBackend::InMem,
+ "sled" => storage::KeyValueStoreBackend::Sled,
+ "btree" => storage::KeyValueStoreBackend::BTreeMap,
+ "rocksdb" => storage::KeyValueStoreBackend::RocksDB,
+ _ => panic!("unknown backend"),
+ },
);
let mut context: Box<dyn ContextApi> = Box::new(TezedgeContext::new(
BlockStorage::new(&storage),
@@ -177,7 +185,7 @@ fn feed_tezedge_context_with_actions() -> Result<(), Error> {
counter += 1;
let progress = counter as f64 / blocks_count as f64 * 100.0;
- match messages.iter().last() {
+ match messages.last() {
Some(action) => match action {
ContextAction::Commit {
block_hash: Some(block_hash),
@@ -200,6 +208,7 @@ fn feed_tezedge_context_with_actions() -> Result<(), Error> {
}
};
+ let mut context_hash_verified = false;
for action in messages.iter() {
if let ContextAction::Commit {
block_hash: Some(block_hash),
@@ -214,6 +223,17 @@ fn feed_tezedge_context_with_actions() -> Result<(), Error> {
block_storage.put_block_header(&b).unwrap();
}
+ // in the begining of the each block there is Checkout message
+ // lets use that and check if current context hash is equal to
+ // one current context hash even before applying the action
+ if let ContextAction::Checkout { context_hash, .. } = action {
+ assert_eq!(
+ context_hash.as_slice(),
+ context.get_last_commit_hash().unwrap().as_slice()
+ );
+ context_hash_verified = true;
+ }
+
match action {
// actions that does not mutate staging area can be ommited here
ContextAction::Set { .. }
@@ -234,17 +254,15 @@ fn feed_tezedge_context_with_actions() -> Result<(), Error> {
};
// verify context hashes after each block
- if let ContextAction::Checkout { context_hash, .. } = action {
- assert_eq!(
- context_hash.as_slice(),
- context.get_last_commit_hash().unwrap().as_slice()
- );
- }
if let Some(expected_hash) = get_new_tree_hash(&action) {
assert_eq!(context.get_merkle_root(), expected_hash);
}
}
+ // ignore genesis_block
+ if counter > 1 {
+ assert!(context_hash_verified);
+ }
}
println!("{:#?}", storage.merkle().read().unwrap().get_merkle_stats());
Ok(())


message: read expected context_hash from ContextAction::Commit

diff:
@@ -208,7 +208,6 @@ fn feed_tezedge_context_with_actions() -> Result<(), Error> {
}
};
- let mut context_hash_verified = false;
for action in messages.iter() {
if let ContextAction::Commit {
block_hash: Some(block_hash),
@@ -223,17 +222,6 @@ fn feed_tezedge_context_with_actions() -> Result<(), Error> {
block_storage.put_block_header(&b).unwrap();
}
- // in the begining of the each block there is Checkout message
- // lets use that and check if current context hash is equal to
- // one current context hash even before applying the action
- if let ContextAction::Checkout { context_hash, .. } = action {
- assert_eq!(
- context_hash.as_slice(),
- context.get_last_commit_hash().unwrap().as_slice()
- );
- context_hash_verified = true;
- }
-
match action {
// actions that does not mutate staging area can be ommited here
ContextAction::Set { .. }
@@ -253,16 +241,22 @@ fn feed_tezedge_context_with_actions() -> Result<(), Error> {
| ContextAction::Shutdown { .. } => {}
};
+ if let ContextAction::Commit {
+ new_context_hash, ..
+ } = action
+ {
+ assert_eq!(
+ new_context_hash.as_slice(),
+ context.get_last_commit_hash().unwrap().as_slice()
+ );
+ }
+
// verify context hashes after each block
if let Some(expected_hash) = get_new_tree_hash(&action) {
assert_eq!(context.get_merkle_root(), expected_hash);
}
}
- // ignore genesis_block
- if counter > 1 {
- assert!(context_hash_verified);
- }
}
println!("{:#?}", storage.merkle().read().unwrap().get_merkle_stats());
Ok(())


message: apply non mutating actions

diff:
@@ -59,7 +59,7 @@ impl ContextActionStoreBackend {
fn supported_values(&self) -> Vec<&'static str> {
match self {
ContextActionStoreBackend::RocksDB => vec!["rocksdb"],
- ContextActionStoreBackend::FileStorage => vec!["file"],
+ ContextActionStoreBackend::FileStorage { .. } => vec!["file"],
ContextActionStoreBackend::NoneBackend => vec!["none"],
}
}
@@ -939,6 +939,15 @@ impl Environment {
|value| {
value
.parse::<KeyValueStoreBackend>()
+ .map(|v| {
+ if let KeyValueStoreBackend::Sled { .. } = v {
+ KeyValueStoreBackend::Sled {
+ path: db_path.join("sled"),
+ }
+ } else {
+ v
+ }
+ })
.expect("Was expecting one value from KeyValueStoreBackend")
},
);

diff:
@@ -134,16 +134,20 @@ fn feed_tezedge_context_with_actions() -> Result<(), Error> {
let header_stub = BlockHeaderWithHash::new(block_header_stub).unwrap();
let cache = Cache::new_lru_cache(128 * 1024 * 1024).unwrap(); // 128 MB
- let commit_log_db_path = PathBuf::from("/tmp/commit_log/");
- let key_value_db_path = PathBuf::from("/tmp/key_value_store/");
+ let out_dir_env = env::var("OUT_DIR")
+ .unwrap_or_else(|_| "/tmp/feed_tezedge_context_with_actions".to_string());
let input_file = env::var("INPUT").expect("test input 'INPUT' not set");
let backend = env::var("BACKEND").expect("test backend 'BACKEND' not set");
+ let out_dir = PathBuf::from(out_dir_env.as_str());
+ let commit_log_db_path = out_dir.join("commit_log");
+ let key_value_db_path = out_dir.join("key_value_store");
+
let actions_storage_path = PathBuf::from(input_file.as_str());
- let _ = fs::remove_dir_all(&commit_log_db_path);
- let _ = fs::remove_dir_all(&key_value_db_path);
+ let _ = fs::remove_dir_all(&out_dir);
+
let logger = create_logger();
let commit_log = create_commit_log(&commit_log_db_path);
@@ -155,7 +159,9 @@ fn feed_tezedge_context_with_actions() -> Result<(), Error> {
commit_log,
match backend.as_str() {
"inmem" => storage::KeyValueStoreBackend::InMem,
- "sled" => storage::KeyValueStoreBackend::Sled,
+ "sled" => storage::KeyValueStoreBackend::Sled {
+ path: out_dir.join("sled"),
+ },
"btree" => storage::KeyValueStoreBackend::BTreeMap,
"rocksdb" => storage::KeyValueStoreBackend::RocksDB,
_ => panic!("unknown backend"),
@@ -229,30 +235,48 @@ fn feed_tezedge_context_with_actions() -> Result<(), Error> {
| ContextAction::Delete { .. }
| ContextAction::RemoveRecursively { .. }
| ContextAction::Commit { .. }
- | ContextAction::Checkout { .. } => {
+ | ContextAction::Checkout { .. }
+ | ContextAction::Get { .. }
+ | ContextAction::Mem { .. }
+ | ContextAction::DirMem { .. }
+ | ContextAction::Fold { .. } => {
if let Err(e) = perform_context_action(&action, &mut context) {
panic!("cannot perform action error: '{}'", e);
}
}
- ContextAction::Get { .. }
- | ContextAction::Mem { .. }
- | ContextAction::DirMem { .. }
- | ContextAction::Fold { .. }
- | ContextAction::Shutdown { .. } => {}
+ ContextAction::Shutdown { .. } => {}
};
- if let ContextAction::Commit {
+ // verify state of the storage after action has been applied
+ match action {
+ ContextAction::Commit {
new_context_hash, ..
- } = action
- {
+ } => {
+ assert_eq!(
+ new_context_hash.clone(),
+ context.get_last_commit_hash().unwrap()
+ );
+ }
+ ContextAction::Checkout { context_hash, .. } => {
+ assert!(!context_hash.is_empty());
assert_eq!(
- new_context_hash.as_slice(),
- context.get_last_commit_hash().unwrap().as_slice()
+ context_hash.clone(),
+ context.get_last_commit_hash().unwrap()
);
}
+ ContextAction::Get { key, value, .. } => {
+ assert_eq!(value.clone(), context.get_key(key).unwrap());
+ }
+ ContextAction::Mem { key, value, .. } => {
+ assert_eq!(*value, context.mem(key).unwrap());
+ }
+ ContextAction::DirMem { key, value, .. } => {
+ assert_eq!(*value, context.dirmem(key).unwrap());
+ }
+ _ => {}
+ };
// verify context hashes after each block
-
if let Some(expected_hash) = get_new_tree_hash(&action) {
assert_eq!(context.get_merkle_root(), expected_hash);
}

diff:
#![feature(allocator_api)]
use std::convert::{TryFrom, TryInto};
-use std::path::Path;
+use std::path::{Path, PathBuf};
use std::sync::Arc;
use failure::Fail;
@@ -476,7 +476,7 @@ pub fn check_database_compatibility(
pub enum KeyValueStoreBackend {
RocksDB,
InMem,
- Sled,
+ Sled { path: PathBuf },
BTreeMap,
}
@@ -493,7 +493,7 @@ impl KeyValueStoreBackend {
match self {
KeyValueStoreBackend::RocksDB => vec!["rocksdb"],
KeyValueStoreBackend::InMem => vec!["inmem"],
- KeyValueStoreBackend::Sled => vec!["sled"],
+ KeyValueStoreBackend::Sled { .. } => vec!["sled"],
KeyValueStoreBackend::BTreeMap => vec!["btree"],
}
}

diff:
@@ -159,8 +159,8 @@ impl PersistentStorage {
MerkleStorage::name(),
))),
KeyValueStoreBackend::InMem => MerkleStorage::new(Box::new(InMemoryBackend::new())),
- KeyValueStoreBackend::Sled => {
- let sled = sled::Config::new().temporary(true).open().unwrap();
+ KeyValueStoreBackend::Sled { path } => {
+ let sled = sled::Config::new().path(path).open().unwrap();
MerkleStorage::new(Box::new(SledBackend::new(sled.deref().clone())))
}
KeyValueStoreBackend::BTreeMap => MerkleStorage::new(Box::new(BTreeMapBackend::new())),

original_message: apply non mutating actions


message: Action recording guide

diff: Binary files a/docs/images/tezedge_explorer.gif and b/docs/images/tezedge_explorer.gif differ

diff:
+### Action Recording
+
+The tezedge node can be used for recording ContextAction that was executed by the node. By default, all the actions are stored in RocksDB database, but also file can be use as a storage.
+There is a dedicated node parameter called `actions-store-backend` that can be used for specifying the desired 'action storage backend'
+
+```
+ --actions-store-backend <STRING>...
+ Activate recording of context storage actions [possible values: none, rocksdb, file]
+```
+
+One can start action recording by running the node:
+
+```
+./run.sh node
+ --tezos-data-dir /tmp/light_node/tezos
+ --bootstrap-db-path /tmp/light_node/tezedge
+ --actions-store-backend file
+ --network=<NETWORK>
+```
+
+there is one extra flag that might be useful:
+
+```
+--compute-context-action-tree-hashes=true
+```
+
+once set ContextActions will include `new_tree_hash` field which is expected context hash *after executing the action*
+
+
+File with already recorded actions can be found in
+```
+/mnt/light_node/tezedge/actionfile.bin
+```
+With every processed block its appended at the end of the file - there is no rewriting of already existing data.
+
+Actions in the file are stored as:
+
+```
+|block1 len in bytes||action 1| action 2| ... | aciton N||block2 len in bytes||action 1| action 2| ... | aciton N|
+<---block 1 header--><-------------block1---------------><---block 2 header--><-------------block2--------------->
+```
+
+where :
+ - `header N` - is unsigned int 32 - lenght of the `N` block
+ - `block N` - Vec<[ContextAction](https://github.com/simplestaking/tezedge/blob/develop/tezos/context/src/channel.rs#L44)> serialized using [bincode crate](https://docs.rs/bincode/1.3.2/bincode/) and then compress using [snap](https://crates.io/crates/snap)
+
+single block is represented as `Vec<ContextAction>`
+
+
+There is dedicated [ActionFileReader](https://github.com/simplestaking/tezedge/blob/develop/storage/src/action_file.rs#L61) that can be used for reading and deserializing following blocks
+
+
+
+
+

original_message: Action recording guide


message:
use_implicit_waits = false properly supports section and sections
EDIT: Also made some syntax changes and amended some cop failures

diff:
@@ -96,3 +96,13 @@ Feature: Waiting for Elements
When I navigate to the home page
Then the slow elements are not waited for
And implicit waits are not enabled
+
+ Scenario: Section Is Not Automatically Waited For
+ When I navigate to the home page
+ Then the slow section is not waited for
+ And implicit waits are not enabled
+
+ Scenario: Sections Collections Are Not Automatically Waited For
+ When I navigate to the home page
+ Then the slow sections are not waited for
+ And implicit waits are not enabled

diff:
@@ -13,3 +13,18 @@ Feature: Waiting for Elements Implicitly
When I navigate to the home page
Then the slow elements are waited for
And implicit waits are enabled
+
+ Scenario: Sections Are Automatically Waited For
+ When I navigate to the home page
+ Then the slow section is waited for
+ And implicit waits are enabled
+
+ Scenario: Sections Collections Are Automatically Waited For
+ When I navigate to the home page
+ Then the slow sections are waited for
+ And implicit waits are enabled
+
+ Scenario: Wait time can be overridden at run-time
+ When I navigate to the home page
+ Then the slow element is waited for only as long as a user set Capybara.using_wait_time
+ And implicit waits are enabled

diff:
@@ -203,3 +203,37 @@ Then(/^the slow elements are not waited for$/) do
expect { @test_site.home.slow_elements(count: 1) }.to raise_error(Capybara::ElementNotFound)
expect(Time.now - start_time).to be < 0.5
end
+
+
+Then(/^the slow section is waited for$/) do
+ start_time = Time.now
+ @test_site.home.slow_section(count: 1)
+ expect(Time.now - start_time).to be > 1.5
+end
+
+Then(/^the slow section is not waited for$/) do
+ start_time = Time.now
+ expect { @test_site.home.slow_section(count: 1) }.to raise_error(Capybara::ElementNotFound)
+ expect(Time.now - start_time).to be < 0.5
+end
+
+Then(/^the slow sections are waited for$/) do
+ start_time = Time.now
+ @test_site.home.slow_sections(count: 2)
+ expect(Time.now - start_time).to be > 1.5
+end
+
+Then(/^the slow sections are not waited for$/) do
+ start_time = Time.now
+ expect { @test_site.home.slow_sections(count: 2) }.to raise_error(Capybara::ElementNotFound)
+ expect(Time.now - start_time).to be < 0.5
+end
+
+Then(/^the slow element is waited for only as long as a user set Capybara.using_wait_time$/) do
+ start_time = Time.now
+ Capybara.using_wait_time(1) do
+ expect { @test_site.home.some_slow_element }.to raise_error(Capybara::ElementNotFound)
+ end
+ expect(Time.now - start_time).to be < 2
+ expect(Time.now - start_time).to be > 0.5
+end

diff:
var t3 = setTimeout("document.getElementById('will_become_invisible').style.display='none';", 2000);
var t4 = setTimeout("document.getElementById('will_become_nonexistent').remove();", 2000);
var t5 = setTimeout("document.getElementById('link_container_will_become_nonexistent').remove();", 2000);
+
+ var slow_section = document.createElement("div");
+ slow_section.className = 'slow-section first';
+ var slow_section2 = document.createElement("div");
+ slow_section2.className = 'slow-section second';
+ setTimeout(function() {
+ [slow_section, slow_section2].forEach(function(item) {
+ dumping_ground.appendChild(item);
+ });
+ }, 2000)
}
window.onload = load;
</script>

diff:
@@ -9,7 +9,7 @@ class TestHomePage < SitePrism::Page
element :welcome_message, 'body > span'
element :go_button, '[value="Go!"]'
element :link_to_search_page, :xpath, '//p[2]/a'
- # This takes just over 2 seconds to appear
+ # Below element takes just over 2 seconds to appear
element :some_slow_element, :xpath, '//a[@class="slow"]'
element :invisible_element, 'input.invisible'
element :shy_element, 'input#will_become_visible'
@@ -25,7 +25,8 @@ class TestHomePage < SitePrism::Page
elements :welcome_headers, :xpath, '//h3'
elements :welcome_messages, :xpath, '//span'
elements :rows, 'td'
- elements :slow_elements, :xpath, '//a[@class="slow"]' # note - actually only one
+ # note - actually only one of the below
+ elements :slow_elements, :xpath, '//a[@class="slow"]'
# elements that should not exist
element :squirrel, 'squirrel.nutz'
@@ -43,12 +44,16 @@ class TestHomePage < SitePrism::Page
section :removing_section,
NoElementWithinSection,
'input#will_become_nonexistent'
+ # `slow_section` takes ~2s to appear
+ section :slow_section, NoElementWithinSection, 'div.first.slow-section'
# section groups
sections :nonexistent_sections, NoElementWithinSection, 'input#nonexistent'
sections :removing_sections,
NoElementWithinSection,
'#link_container_will_become_nonexistent > a'
+ # `slow_sections` takes ~2s to appear
+ sections :slow_sections, NoElementWithinSection, 'div.slow-section'
# iframes
iframe :my_iframe, MyIframe, '#the_iframe'

license: BSD 3-Clause New or Revised License


message: Add some documentation on Capybara Implicit Waits

diff:
@@ -1733,6 +1733,18 @@ with this:
@search_page.search_results
```
+Note that even with implicit waits on you can temporarily modify wait times in SitePrism to help work-around special circumstances.
+
+```rb
+# Option 1: using wait_for
+@search_page.wait_for_search_results(30) # will wait up to 30seconds
+
+# Option 2: using Capybara directly
+Capybara.using_wait_time(30) do
+ @search_page.subsection.search_results
+end
+```
+
## Raising Errors on wait_for
By default, when using `wait_for_*` and `wait_for_no_*` methods, SitePrism will not raise