Repository: pingcap/talent-plan Branch: master Commit: 18d81c90e403 Files: 195 Total size: 1.6 MB Directory structure: gitextract_2klmrfgy/ ├── .circleci/ │ └── config.yml ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug-report.md │ │ ├── feature-requirement.md │ │ └── question.md │ └── pull_request_template.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── README.md ├── courses/ │ ├── README.md │ ├── dss/ │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── Makefile │ │ ├── README.md │ │ ├── labcodec/ │ │ │ ├── Cargo.toml │ │ │ ├── build.rs │ │ │ ├── demonstration/ │ │ │ │ ├── README.md │ │ │ │ └── expanded_fixture.rs │ │ │ ├── proto/ │ │ │ │ └── fixture.proto │ │ │ └── src/ │ │ │ └── lib.rs │ │ ├── labrpc/ │ │ │ ├── Cargo.toml │ │ │ ├── benches/ │ │ │ │ └── rpc.rs │ │ │ ├── examples/ │ │ │ │ └── echo.rs │ │ │ └── src/ │ │ │ ├── client.rs │ │ │ ├── error.rs │ │ │ ├── lib.rs │ │ │ ├── macros.rs │ │ │ ├── network.rs │ │ │ └── server.rs │ │ ├── linearizability/ │ │ │ ├── Cargo.toml │ │ │ ├── src/ │ │ │ │ ├── bitset.rs │ │ │ │ ├── lib.rs │ │ │ │ ├── model.rs │ │ │ │ └── models.rs │ │ │ └── test_data/ │ │ │ ├── c01-bad.txt │ │ │ ├── c01-ok.txt │ │ │ ├── c10-bad.txt │ │ │ ├── c10-ok.txt │ │ │ ├── c50-bad.txt │ │ │ └── c50-ok.txt │ │ ├── percolator/ │ │ │ ├── Cargo.toml │ │ │ ├── README.md │ │ │ ├── build.rs │ │ │ ├── proto/ │ │ │ │ └── msg.proto │ │ │ └── src/ │ │ │ ├── client.rs │ │ │ ├── lib.rs │ │ │ ├── server.rs │ │ │ ├── service.rs │ │ │ └── tests.rs │ │ └── raft/ │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── build.rs │ │ └── src/ │ │ ├── kvraft/ │ │ │ ├── client.rs │ │ │ ├── config.rs │ │ │ ├── errors.rs │ │ │ ├── mod.rs │ │ │ ├── server.rs │ │ │ └── tests.rs │ │ ├── lib.rs │ │ ├── proto/ │ │ │ ├── kvraft.proto │ │ │ ├── mod.rs │ │ │ └── raft.proto │ │ └── raft/ │ │ ├── config.rs │ │ ├── errors.rs │ │ ├── mod.rs │ │ ├── persister.rs │ │ └── tests.rs │ ├── rust/ │ │ ├── .gitignore │ │ ├── CONTRIBUTING.md │ │ ├── README.md │ │ ├── building-blocks/ │ │ │ ├── bb-1.md │ │ │ ├── bb-2.md │ │ │ ├── bb-3.md │ │ │ ├── bb-4.md │ │ │ └── bb-5.md │ │ ├── docs/ │ │ │ ├── etc/ │ │ │ │ ├── notes.md │ │ │ │ └── parallel-diagrams.txt │ │ │ ├── lesson-plan.md │ │ │ ├── prerequisites.md │ │ │ ├── roadmap.md │ │ │ └── what-next.md │ │ └── projects/ │ │ ├── project-1/ │ │ │ ├── Cargo.toml │ │ │ ├── README.md │ │ │ ├── src/ │ │ │ │ ├── bin/ │ │ │ │ │ └── kvs.rs │ │ │ │ ├── kv.rs │ │ │ │ └── lib.rs │ │ │ └── tests/ │ │ │ └── tests.rs │ │ ├── project-2/ │ │ │ ├── Cargo.toml │ │ │ ├── README.md │ │ │ ├── src/ │ │ │ │ ├── bin/ │ │ │ │ │ └── kvs.rs │ │ │ │ ├── error.rs │ │ │ │ ├── kv.rs │ │ │ │ └── lib.rs │ │ │ └── tests/ │ │ │ └── tests.rs │ │ ├── project-3/ │ │ │ ├── Cargo.toml │ │ │ ├── README.md │ │ │ ├── benches/ │ │ │ │ └── engine_bench.rs │ │ │ ├── src/ │ │ │ │ ├── bin/ │ │ │ │ │ ├── kvs-client.rs │ │ │ │ │ └── kvs-server.rs │ │ │ │ ├── client.rs │ │ │ │ ├── common.rs │ │ │ │ ├── engines/ │ │ │ │ │ ├── kvs.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ └── sled.rs │ │ │ │ ├── error.rs │ │ │ │ ├── lib.rs │ │ │ │ └── server.rs │ │ │ └── tests/ │ │ │ ├── cli.rs │ │ │ └── kv_store.rs │ │ ├── project-4/ │ │ │ ├── Cargo.toml │ │ │ ├── README.md │ │ │ ├── src/ │ │ │ │ ├── bin/ │ │ │ │ │ ├── kvs-client.rs │ │ │ │ │ └── kvs-server.rs │ │ │ │ ├── client.rs │ │ │ │ ├── common.rs │ │ │ │ ├── engines/ │ │ │ │ │ ├── kvs.rs │ │ │ │ │ ├── mod.rs │ │ │ │ │ └── sled.rs │ │ │ │ ├── error.rs │ │ │ │ ├── lib.rs │ │ │ │ ├── server.rs │ │ │ │ └── thread_pool/ │ │ │ │ ├── mod.rs │ │ │ │ ├── naive.rs │ │ │ │ ├── rayon.rs │ │ │ │ └── shared_queue.rs │ │ │ └── tests/ │ │ │ ├── cli.rs │ │ │ ├── kv_store.rs │ │ │ └── thread_pool.rs │ │ └── project-5/ │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── src/ │ │ │ ├── bin/ │ │ │ │ ├── kvs-client.rs │ │ │ │ └── kvs-server.rs │ │ │ ├── client.rs │ │ │ ├── common.rs │ │ │ ├── engines/ │ │ │ │ ├── kvs.rs │ │ │ │ ├── mod.rs │ │ │ │ └── sled.rs │ │ │ ├── error.rs │ │ │ ├── lib.rs │ │ │ ├── server.rs │ │ │ └── thread_pool/ │ │ │ ├── mod.rs │ │ │ ├── naive.rs │ │ │ ├── rayon.rs │ │ │ └── shared_queue.rs │ │ └── tests/ │ │ ├── cli.rs │ │ ├── kv_store.rs │ │ └── thread_pool.rs │ ├── tp101-intro-to-oss.md │ ├── tp102-how-to-use-git-github.md │ └── tp103-open-source-community.md ├── talent-challenge-program/ │ ├── MENTEE_APPLY_TEMPLATE.md │ ├── PROJECT_IDEA_TEMPLATE.md │ ├── README.md │ ├── project-ideas.md │ ├── s1.md │ └── selected-projects.md ├── talent-challenge-program2021/ │ ├── MENTEE_APPLY_TEMPLATE.md │ ├── PROJECT_IDEA_TEMPLATE.md │ ├── README.md │ ├── project-ideas.md │ ├── schedule.md │ └── selected-projects.md ├── talent-plan-1.0/ │ ├── 1.0-lp-tidb.md │ ├── 1.0-lp-tikv.md │ └── README-CN.md └── tidb/ ├── .gitignore ├── README.md ├── join/ │ ├── Makefile │ ├── README.md │ ├── benchmark_test.go │ ├── go.mod │ ├── go.sum │ ├── join.go │ ├── join_example.go │ ├── join_test.go │ └── t/ │ ├── r0.tbl │ ├── r1.tbl │ └── r2.tbl ├── mapreduce/ │ ├── .gitignore │ ├── Makefile │ ├── README.md │ ├── casegen.go │ ├── go.mod │ ├── go.sum │ ├── mapreduce.go │ ├── urltop10.go │ ├── urltop10_example.go │ ├── urltop10_test.go │ └── utils.go └── mergesort/ ├── Makefile ├── README.md ├── bench_test.go ├── go.mod ├── go.sum ├── mergesort.go └── mergesort_test.go ================================================ FILE CONTENTS ================================================ ================================================ FILE: .circleci/config.yml ================================================ version: 2.1 jobs: dss: docker: - image: circleci/rust:stretch environment: RUST_BACKTRACE: "1" RUSTFLAGS: "-Dwarnings" working_directory: ~/talent-plan/courses/dss steps: - checkout: path: ~/talent-plan - run: rustup component add clippy-preview rustfmt-preview - run: cargo fmt --all -- --check - run: cargo clippy --all --tests -- -D clippy::all - run: cargo test -p labcodec -p labrpc - run: cargo test -p raft -- --test raft::persister - run: command: cargo test -p linearizability no_output_timeout: 30m workflows: version: 2 ci-test: jobs: - dss ================================================ FILE: .github/ISSUE_TEMPLATE/bug-report.md ================================================ --- name: "\U0001F41B Bug Report" about: something isn't working as expected labels: type/bug --- ## Bug Report Please answer these questions before submitting your issue. Thanks! ### 1. What did you do? ### 2. What did you expect to see? ### 3. What did you see instead? ================================================ FILE: .github/ISSUE_TEMPLATE/feature-requirement.md ================================================ --- name: "\U0001F680 Feature Request" about: I have a suggestion! labels: type/enhancement --- ## Feature Request please make a clear and concise description for the following questions. ### Is your feature request related to a problem? ### Describe the feature you'd like ### Describe alternatives you've considered ================================================ FILE: .github/ISSUE_TEMPLATE/question.md ================================================ --- name: "\U0001F914 Question" about: I have a question! labels: type/question --- ## General Question ## Tips Expect for asking questions on Github, you can also discuss it in the channel **#wg-talent-plan-courses**. of [tidbcommunity](https://join.slack.com/t/tidbcommunity/shared_invite/enQtNzc0MzI4ODExMDc4LWYwYmIzMjZkYzJiNDUxMmZlN2FiMGJkZjAyMzQ5NGU0NGY0NzI3NTYwMjAyNGQ1N2I2ZjAxNzc1OGUwYWM0NzE) slack workspace. ================================================ FILE: .github/pull_request_template.md ================================================ ### What problem does this PR solve? - Issue number: close #xxx - Breif description of the problem: ### What is changed and how it works? ### Check List Tests - Unit test - Integration test - Manual test (add detailed scripts or steps below) - No code Side effects - Possible performance regression - Increased code complexity Related changes - Need to update the documentation ================================================ FILE: CODE_OF_CONDUCT.md ================================================ # Contributor Covenant Code of Conduct ## Our Pledge In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. ## Our Standards Examples of behavior that contributes to creating a positive environment include: * Using welcoming and inclusive language * Being respectful of differing viewpoints and experiences * Gracefully accepting constructive criticism * Focusing on what is best for the community * Showing empathy towards other community members Examples of unacceptable behavior by participants include: * The use of sexualized language or imagery and unwelcome sexual attention or advances * Trolling, insulting/derogatory comments, and personal or political attacks * Public or private harassment * Publishing others' private information, such as a physical or electronic address, without explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. ## Scope This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [ts-team@pingcap.com](mailto:ts-team@pingcap.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. ## Attribution This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html [homepage]: https://www.contributor-covenant.org For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing Guide Thanks for taking the time to contribute to Talent Plan! Contributions of any kind are welcome. ## Ways to contribute We love contributions from the community. Here are just a few of the ways you can contribute: - **Report bugs:** if you find a bug while taking courses, you may want to do a quick check of past issues to see if you can find any help there. Otherwise, create a new bug issue in the course repository using the provided template. - **Answer questions:** check out the open issues to see if you can help answer learner questions. - **Suggest changes:** this could come in the form of a new learning outcome, updates to the content, updates to the bot responses, or the logic of the course. If you'd like, you can fork the course and suggest the change that way, but most people like to talk about it first in an issue. - **Tackle an issue:** if you see an issue you would like to resolve, please feel free to fork the course and submit a PR (check out the instructions below). - **Translate a course:** if you have the ability to translate a course, we'd love to see it. Please fork the course and submit a PR. We'll need a second native speaker to confirm the translation so if you have anyone in mind, please @ mention them in your PR for a review. ## How to Contribute 1. Check out which [contributions](#ways-to-contribute) above you are willing to make 1. Fork this repository. 2. Commit your changes to your branch 3. Open a pull request to upstream 4. Request a review from the reviewers Want to konw more about how to use Git & GitHub to make contributions? Click [how to use Git & GitHub](courses/tp102-how-to-use-git-github.md) courses for more help ================================================ FILE: README.md ================================================ # Welcome to learn Talent Plan Courses! ![Talent Plan Logo](media/talent-plan-logo.png) Talent Plan is an open source training program initiated by PingCAP. It aims to create or combine some open source learning materials for people interested in open source, distributed systems, Rust, Golang, and other infrastructure knowledge. As such, it provides a series of courses focused on open source collaboration, rust programming, distributed database and systems. > Note: > Each course is developed by different teams, so they may vary in their organization and learning outcomes. Please see the individual course documentation for details. ## Our Courses ### Series 1: Open Source Collaboration Open source collaboration includes a series of open-source related learning materials to help enthusiasts gain basic knowledge of what open source software is, the differences between existing open-source software licenses, how to participate in open source projects, and what a welcoming open source community looks like. Courses include: - [TP 101: Introduction to open source software](courses/tp101-intro-to-oss.md) - [TP 102: How to use Git and GitHub](courses/tp102-how-to-use-git-github.md) - [TP 103: Build a welcoming community](courses/tp103-open-source-community.md) ### Series 2: Rust Programming This series is core to TALENT-PLAN. It builds your understanding of Rust as a programming language and provides opportunities for you to practice with it. Courses include: - [TP 201: Practical Networked Applications in Rust](courses/rust/README.md). A series of projects that incrementally develop a single Rust project from the ground up into a high-performance, networked, parallel and asynchronous key/value store. Along the way various real-world Rust development subject matter are explored and discussed. - [TP 202: Distributed Systems in Rust](courses/dss/README.md). Adapted from the [MIT 6.824](http://nil.csail.mit.edu/6.824/2017/index.html) distributed systems coursework, this course focuses on implementing important distributed algorithms, including the [Raft](https://raft.github.io/) consensus algorithm, and the [Percolator](https://storage.googleapis.com/pub-tools-public-publication-data/pdf/36726.pdf) distributed transaction protocol. ### Series 3: Distributed Database This series provides information on TinySQL and TinyKV, which are distributed databases in Go. Courses include: - [TP 301: TinySQL, a distributed relational database in Go](https://github.com/pingcap-incubator/tinysql) - [TP 302: TinyKV, a distributed key value database in Go](https://github.com/pingcap-incubator/tinykv) ### Series 4: Deep Dive into TiDB Ecosystems This series provides information on TiDB and TiKV, which are distributed databases developed by PingCAP. Courses include: - TP 401: Deep Dive into TiDB(WIP) - TP 402: Deep Dive into TiKV(WIP) See [Courses](courses/README.md) for more details. # Contributing to talent plan Contributions of any kind are welcome! Check out the [Contributing Guide](CONTRIBUTING.md) in this repository for more information on how you can contribute to Talent Plan. We love our community and take great care to ensure it is fun, safe and rewarding. Please review our [Code of Conduct](/CODE_OF_CONDUCT.md) for community expectations and guidelines for reporting concerns. ## We're here to help If you have questions about building (or taking) courses, you can ask in the channel **#wg-talent-plan-courses** of the [tidbcommunity](https://tidbcommunity.slack.com/join/shared_invite/enQtNzc0MzI4ODExMDc4LWYwYmIzMjZkYzJiNDUxMmZlN2FiMGJkZjAyMzQ5NGU0NGY0NzI3NTYwMjAyNGQ1N2I2ZjAxNzc1OGUwYWM0NzE#/shared-invite/email) slack workspace. ## License These courses may be freely used and modified for any purpose, under the terms of each course's individual license. See the courses for details. ================================================ FILE: courses/README.md ================================================ # All public courses Here we list all public courses of Talent Plan, including: - [TP 101: Introduction to open source software](tp101-intro-to-oss.md) - [TP 102: How to use Git and GitHub](tp102-how-to-use-git-github.md) - [TP 103: Build a welcoming community](tp103-open-source-community.md) - [TP 201: Practical Networked Applications in Rust](rust/README.md) - [TP 202: Distributed Systems in Rust](dss/README.md) - [TP 301: TinySQL, a distributed relational database in Go](https://github.com/pingcap-incubator/tinysql) - [TP 302: TinyKV, a distributed key value database in Go](https://github.com/pingcap-incubator/tinykv) - TP 401: Deep Dive into TiDB(WIP) - TP 402: Deep Dive into TiKV(WIP) ================================================ FILE: courses/dss/.gitignore ================================================ **/target **/*.rs.bk 6.824-golabs-2018 ================================================ FILE: courses/dss/Cargo.toml ================================================ [workspace] members = [ "labcodec", "labrpc", "linearizability", "raft", "percolator" ] ================================================ FILE: courses/dss/Makefile ================================================ export RUSTFLAGS=-Dwarnings export RUST_TEST_THREADS=1 export RUST_BACKTRACE=1 LOG_LEVEL ?= raft=info,percolator=info check: cargo fmt --all -- --check cargo clippy --all --tests -- -D clippy::all test: test_others test_2 test_3 test_2: test_2a test_2b test_2c test_2d test_2a: cargo_test_2a test_2b: cargo_test_2b test_2c: cargo_test_2c test_2d: cargo_test_2d test_3: test_3a test_3b test_3a: cargo_test_3a test_3b: cargo_test_3b cargo_test_%: check RUST_LOG=${LOG_LEVEL} cargo test -p raft -- --nocapture --test $* test_others: check RUST_LOG=${LOG_LEVEL} cargo test -p labrpc -p labcodec -- --nocapture test_percolator: check RUST_LOG=${LOG_LEVEL} cargo test -p percolator -- --nocapture ================================================ FILE: courses/dss/README.md ================================================ # Distributed Systems in Rust A training course about the distributed systems in [Rust]. Subjects covered include: - [Raft consensus algorithm] (including a fault-tolerant key-value storage service using Raft) - [Percolator transaction model] After completing this course you will have the knowledge to implement a basic key-value storage service with transaction and fault-tolerant in Rust. **Important note: Distributed Systems in Rust is in an alpha state** It might contain bugs. Any feedback is greatly appreciated. Please [file issues] if you have any problem. And also You are encouraged to fix problems on your own and submit pull requests. ## The goal of this course The goal of this course is to teach the Rust programmers who are interested in distributed systems to know about how to make the distributed systems reliable and how to implement the distributed transaction. ## Who is this for? Distributed Systems in Rust is for experienced _Rust_ programmers, who are familiar with the Rust language. If you are not, you can first learn our [rust] lessons. ## A PingCAP-specific note This course, combined with [Deep Dive TiKV], is intended to be enough to enable programmers to meaningfully contribute to [TiKV]. It is most specifically designed to teach those in the Chinese Rust community enough Rust to work on TiKV. The language used is intended to be simple so that those who read only a little English can follow. If you find any of the language difficult to understand please [file issues]. ## License [CC-BY 4.0](https://opendefinition.org/licenses/cc-by/) [rust]: ../rust/README.md [file issues]: https://github.com/pingcap/talent-plan/issues/ [Deep Dive TiKV]: https://tikv.github.io/deep-dive-tikv/overview/introduction.html [TiKV]: https://github.com/tikv/tikv/ [Rust]: https://www.rust-lang.org/ [Raft consensus algorithm]: raft/README.md [Percolator transaction model]: percolator/README.md ================================================ FILE: courses/dss/labcodec/Cargo.toml ================================================ [package] name = "labcodec" version = "0.1.0" build = "build.rs" edition = "2018" publish = false [dependencies] prost = "0.6" [build-dependencies] prost-build = "0.6" ================================================ FILE: courses/dss/labcodec/build.rs ================================================ fn main() { prost_build::compile_protos(&["proto/fixture.proto"], &["proto"]).unwrap(); println!("cargo:rerun-if-changed=proto"); } ================================================ FILE: courses/dss/labcodec/demonstration/README.md ================================================ # Demonstration Expanded version of generated rust files. Files in the folder are for the sake of understanding how procedural macro works, and they are not compilable. ================================================ FILE: courses/dss/labcodec/demonstration/expanded_fixture.rs ================================================ /// A simple protobuf message. pub struct Msg { #[prost(enumeration = "msg::Type", tag = "1")] pub r#type: i32, #[prost(uint64, tag = "2")] pub id: u64, #[prost(string, tag = "3")] pub name: std::string::String, #[prost(bytes, repeated, tag = "4")] pub paylad: ::std::vec::Vec>, } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::clone::Clone for Msg { #[inline] fn clone(&self) -> Msg { match *self { Msg { r#type: ref __self_0_0, id: ref __self_0_1, name: ref __self_0_2, paylad: ref __self_0_3, } => Msg { r#type: ::core::clone::Clone::clone(&(*__self_0_0)), id: ::core::clone::Clone::clone(&(*__self_0_1)), name: ::core::clone::Clone::clone(&(*__self_0_2)), paylad: ::core::clone::Clone::clone(&(*__self_0_3)), }, } } } impl ::core::marker::StructuralPartialEq for Msg {} #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::PartialEq for Msg { #[inline] fn eq(&self, other: &Msg) -> bool { match *other { Msg { r#type: ref __self_1_0, id: ref __self_1_1, name: ref __self_1_2, paylad: ref __self_1_3, } => match *self { Msg { r#type: ref __self_0_0, id: ref __self_0_1, name: ref __self_0_2, paylad: ref __self_0_3, } => { (*__self_0_0) == (*__self_1_0) && (*__self_0_1) == (*__self_1_1) && (*__self_0_2) == (*__self_1_2) && (*__self_0_3) == (*__self_1_3) } }, } } #[inline] fn ne(&self, other: &Msg) -> bool { match *other { Msg { r#type: ref __self_1_0, id: ref __self_1_1, name: ref __self_1_2, paylad: ref __self_1_3, } => match *self { Msg { r#type: ref __self_0_0, id: ref __self_0_1, name: ref __self_0_2, paylad: ref __self_0_3, } => { (*__self_0_0) != (*__self_1_0) || (*__self_0_1) != (*__self_1_1) || (*__self_0_2) != (*__self_1_2) || (*__self_0_3) != (*__self_1_3) } }, } } } impl ::prost::Message for Msg { #[allow(unused_variables)] fn encode_raw(&self, buf: &mut B) where B: ::prost::bytes::BufMut, { if self.r#type != msg::Type::default() as i32 { ::prost::encoding::int32::encode(1u32, &self.r#type, buf); } if self.id != 0u64 { ::prost::encoding::uint64::encode(2u32, &self.id, buf); } if self.name != "" { ::prost::encoding::string::encode(3u32, &self.name, buf); } ::prost::encoding::bytes::encode_repeated(4u32, &self.paylad, buf); } #[allow(unused_variables)] fn merge_field( &mut self, tag: u32, wire_type: ::prost::encoding::WireType, buf: &mut B, ctx: ::prost::encoding::DecodeContext, ) -> ::std::result::Result<(), ::prost::DecodeError> where B: ::prost::bytes::Buf, { const STRUCT_NAME: &'static str = "Msg"; match tag { 1u32 => { let mut value = &mut self.r#type; ::prost::encoding::int32::merge(wire_type, value, buf, ctx).map_err(|mut error| { error.push(STRUCT_NAME, "r#type"); error }) } 2u32 => { let mut value = &mut self.id; ::prost::encoding::uint64::merge(wire_type, value, buf, ctx).map_err(|mut error| { error.push(STRUCT_NAME, "id"); error }) } 3u32 => { let mut value = &mut self.name; ::prost::encoding::string::merge(wire_type, value, buf, ctx).map_err(|mut error| { error.push(STRUCT_NAME, "name"); error }) } 4u32 => { let mut value = &mut self.paylad; ::prost::encoding::bytes::merge_repeated(wire_type, value, buf, ctx).map_err( |mut error| { error.push(STRUCT_NAME, "paylad"); error }, ) } _ => ::prost::encoding::skip_field(wire_type, tag, buf, ctx), } } #[inline] fn encoded_len(&self) -> usize { 0 + if self.r#type != msg::Type::default() as i32 { ::prost::encoding::int32::encoded_len(1u32, &self.r#type) } else { 0 } + if self.id != 0u64 { ::prost::encoding::uint64::encoded_len(2u32, &self.id) } else { 0 } + if self.name != "" { ::prost::encoding::string::encoded_len(3u32, &self.name) } else { 0 } + ::prost::encoding::bytes::encoded_len_repeated(4u32, &self.paylad) } fn clear(&mut self) { self.r#type = msg::Type::default() as i32; self.id = 0u64; self.name.clear(); self.paylad.clear(); } } impl Default for Msg { fn default() -> Msg { Msg { r#type: msg::Type::default() as i32, id: 0u64, name: ::std::string::String::new(), paylad: ::std::vec::Vec::new(), } } } impl ::std::fmt::Debug for Msg { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { let mut builder = f.debug_struct("Msg"); let builder = { let wrapper = { struct ScalarWrapper<'a>(&'a i32); impl<'a> ::std::fmt::Debug for ScalarWrapper<'a> { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { match msg::Type::from_i32(*self.0) { None => ::std::fmt::Debug::fmt(&self.0, f), Some(en) => ::std::fmt::Debug::fmt(&en, f), } } } ScalarWrapper(&self.r#type) }; builder.field("r#type", &wrapper) }; let builder = { let wrapper = { fn ScalarWrapper(v: T) -> T { v } ScalarWrapper(&self.id) }; builder.field("id", &wrapper) }; let builder = { let wrapper = { fn ScalarWrapper(v: T) -> T { v } ScalarWrapper(&self.name) }; builder.field("name", &wrapper) }; let builder = { let wrapper = { struct ScalarWrapper<'a>(&'a ::std::vec::Vec<::std::vec::Vec>); impl<'a> ::std::fmt::Debug for ScalarWrapper<'a> { fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { let mut vec_builder = f.debug_list(); for v in self.0 { fn Inner(v: T) -> T { v } vec_builder.entry(&Inner(v)); } vec_builder.finish() } } ScalarWrapper(&self.paylad) }; builder.field("paylad", &wrapper) }; builder.finish() } } #[allow(dead_code)] impl Msg { ///Returns the enum value of `type`, or the default if the field is set to an invalid enum value. pub fn r#type(&self) -> msg::Type { msg::Type::from_i32(self.r#type).unwrap_or(msg::Type::default()) } ///Sets `type` to the provided enum value. pub fn set_type(&mut self, value: msg::Type) { self.r#type = value as i32; } } pub mod msg { #[repr(i32)] pub enum Type { Unknown = 0, Put = 1, Get = 2, Del = 3, } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::clone::Clone for Type { #[inline] fn clone(&self) -> Type { { *self } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::marker::Copy for Type {} #[automatically_derived] #[allow(unused_qualifications)] impl ::core::fmt::Debug for Type { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match (&*self,) { (&Type::Unknown,) => { let mut debug_trait_builder = f.debug_tuple("Unknown"); debug_trait_builder.finish() } (&Type::Put,) => { let mut debug_trait_builder = f.debug_tuple("Put"); debug_trait_builder.finish() } (&Type::Get,) => { let mut debug_trait_builder = f.debug_tuple("Get"); debug_trait_builder.finish() } (&Type::Del,) => { let mut debug_trait_builder = f.debug_tuple("Del"); debug_trait_builder.finish() } } } } impl ::core::marker::StructuralPartialEq for Type {} #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::PartialEq for Type { #[inline] fn eq(&self, other: &Type) -> bool { { let __self_vi = unsafe { ::core::intrinsics::discriminant_value(&*self) } as i32; let __arg_1_vi = unsafe { ::core::intrinsics::discriminant_value(&*other) } as i32; if true && __self_vi == __arg_1_vi { match (&*self, &*other) { _ => true, } } else { false } } } } impl ::core::marker::StructuralEq for Type {} #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::Eq for Type { #[inline] #[doc(hidden)] fn assert_receiver_is_total_eq(&self) -> () { {} } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::hash::Hash for Type { fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () { match (&*self,) { _ => ::core::hash::Hash::hash( &unsafe { ::core::intrinsics::discriminant_value(self) }, state, ), } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::PartialOrd for Type { #[inline] fn partial_cmp(&self, other: &Type) -> ::core::option::Option<::core::cmp::Ordering> { { let __self_vi = unsafe { ::core::intrinsics::discriminant_value(&*self) } as i32; let __arg_1_vi = unsafe { ::core::intrinsics::discriminant_value(&*other) } as i32; if true && __self_vi == __arg_1_vi { match (&*self, &*other) { _ => ::core::option::Option::Some(::core::cmp::Ordering::Equal), } } else { __self_vi.partial_cmp(&__arg_1_vi) } } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::Ord for Type { #[inline] fn cmp(&self, other: &Type) -> ::core::cmp::Ordering { { let __self_vi = unsafe { ::core::intrinsics::discriminant_value(&*self) } as i32; let __arg_1_vi = unsafe { ::core::intrinsics::discriminant_value(&*other) } as i32; if true && __self_vi == __arg_1_vi { match (&*self, &*other) { _ => ::core::cmp::Ordering::Equal, } } else { __self_vi.cmp(&__arg_1_vi) } } } } impl Type { ///Returns `true` if `value` is a variant of `Type`. pub fn is_valid(value: i32) -> bool { match value { 0 => true, 1 => true, 2 => true, 3 => true, _ => false, } } ///Converts an `i32` to a `Type`, or `None` if `value` is not a valid variant. pub fn from_i32(value: i32) -> ::std::option::Option { match value { 0 => ::std::option::Option::Some(Type::Unknown), 1 => ::std::option::Option::Some(Type::Put), 2 => ::std::option::Option::Some(Type::Get), 3 => ::std::option::Option::Some(Type::Del), _ => ::std::option::Option::None, } } } impl ::std::default::Default for Type { fn default() -> Type { Type::Unknown } } impl ::std::convert::From for i32 { fn from(value: Type) -> i32 { value as i32 } } } ================================================ FILE: courses/dss/labcodec/proto/fixture.proto ================================================ syntax = "proto3"; package fixture; // A simple protobuf message. message Msg { enum Type { UNKNOWN = 0; PUT = 1; GET = 2; DEL = 3; } Type type = 1; uint64 id = 2; string name = 3; repeated bytes paylad = 4; } ================================================ FILE: courses/dss/labcodec/src/lib.rs ================================================ //! A thin wrapper of [prost](https://docs.rs/prost/0.6.1/prost/) /// A labcodec message. pub trait Message: prost::Message + Default {} impl Message for T {} /// A message encoding error. pub type EncodeError = prost::EncodeError; /// A message decoding error. pub type DecodeError = prost::DecodeError; /// Encodes the message to a `Vec`. pub fn encode(message: &M, buf: &mut Vec) -> Result<(), EncodeError> { buf.reserve(message.encoded_len()); message.encode(buf)?; Ok(()) } /// Decodes an message from the buffer. pub fn decode(buf: &[u8]) -> Result { M::decode(buf) } #[cfg(test)] mod tests { mod fixture { // The generated rust file: // labs6824/target/debug/build/labcodec-hashhashhashhash/out/fixture.rs // // It looks like: // // ```no_run // /// A simple protobuf message. // #[derive(Clone, PartialEq, Message)] // pub struct Msg { // #[prost(enumeration="msg::Type", tag="1")] // pub type_: i32, // #[prost(uint64, tag="2")] // pub id: u64, // #[prost(string, tag="3")] // pub name: String, // #[prost(bytes, repeated, tag="4")] // pub paylad: ::std::vec::Vec>, // } // pub mod msg { // #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Enumeration)] // pub enum Type { // Unknown = 0, // Put = 1, // Get = 2, // Del = 3, // } // } // ``` include!(concat!(env!("OUT_DIR"), "/fixture.rs")); } use super::{decode, encode}; #[test] fn test_basic_encode_decode() { let msg = fixture::Msg { r#type: fixture::msg::Type::Put as _, id: 42, name: "the answer".to_owned(), paylad: vec![vec![7; 3]; 2], }; let mut buf = vec![]; encode(&msg, &mut buf).unwrap(); let msg1 = decode(&buf).unwrap(); assert_eq!(msg, msg1); } #[test] fn test_default() { let msg = fixture::Msg::default(); let msg1 = decode(&[]).unwrap(); assert_eq!(msg, msg1); } } ================================================ FILE: courses/dss/labrpc/Cargo.toml ================================================ [package] name = "labrpc" version = "0.1.0" edition = "2018" publish = false [dependencies] async-trait = "0.1" futures = { version = "0.3", features = ["thread-pool"] } futures-timer = "3.0" log = "0.4" prost = "0.6" rand = "0.7" labcodec = { path = "../labcodec" } [dev-dependencies] criterion = "0.3" env_logger = "0.7" prost-derive = "0.6" [[bench]] name = "rpc" path = "benches/rpc.rs" harness = false ================================================ FILE: courses/dss/labrpc/benches/rpc.rs ================================================ use std::sync::{Arc, Mutex}; use criterion::{black_box, criterion_group, criterion_main, Criterion}; use futures::executor::block_on; use prost_derive::Message; use labrpc::{service, Network, Result, Server, ServerBuilder}; service! { /// A simple bench-purpose service. service bench { /// Doc comments. rpc handler(BenchArgs) returns (BenchReply); } } use bench::{add_service, Client as BenchClient, Service}; // Hand-written protobuf messages. #[derive(Clone, PartialEq, Message)] pub struct BenchArgs { #[prost(int64, tag = "1")] pub x: i64, } #[derive(Clone, PartialEq, Message)] pub struct BenchReply { #[prost(string, tag = "1")] pub x: String, } #[derive(Default)] struct BenchInner { log2: Vec, } #[derive(Clone)] pub struct BenchService { inner: Arc>, } impl BenchService { fn new() -> BenchService { BenchService { inner: Arc::default(), } } } #[async_trait::async_trait] impl Service for BenchService { async fn handler(&self, args: BenchArgs) -> Result { self.inner.lock().unwrap().log2.push(args.x); Ok(BenchReply { x: format!("handler-{}", args.x), }) } } fn bench_suit() -> (Network, Server, BenchService) { let net = Network::new(); let server_name = "test_server".to_owned(); let mut builder = ServerBuilder::new(server_name); let bench_server = BenchService::new(); add_service(bench_server.clone(), &mut builder).unwrap(); let server = builder.build(); net.add_server(server.clone()); (net, server, bench_server) } fn bench_rpc(c: &mut Criterion) { let (net, server, _bench_server) = bench_suit(); let server_name = server.name(); let client_name = "client"; let client = BenchClient::new(net.create_client(client_name.to_owned())); net.connect(client_name, server_name); net.enable(client_name, true); c.bench_function("rpc", |b| { b.iter(|| { black_box(block_on(async { client.handler(&BenchArgs { x: 111 }).await.unwrap() })); }) // i7-8650U, 13 microseconds per RPC }); } criterion_group!(benches, bench_rpc); criterion_main!(benches); ================================================ FILE: courses/dss/labrpc/examples/echo.rs ================================================ use futures::executor::block_on; use prost_derive::Message; use labrpc::*; /// A Hand-written protobuf messages #[derive(Clone, PartialEq, Message)] pub struct Echo { #[prost(int64, tag = "1")] pub x: i64, } service! { service echo { rpc ping(Echo) returns (Echo); } } use echo::{add_service, Client, Service}; #[derive(Clone)] struct EchoService; #[async_trait::async_trait] impl Service for EchoService { async fn ping(&self, input: Echo) -> Result { Ok(input) } } fn main() { let rn = Network::new(); let server_name = "echo_server"; let mut builder = ServerBuilder::new(server_name.to_owned()); add_service(EchoService, &mut builder).unwrap(); let server = builder.build(); rn.add_server(server); let client_name = "client"; let client = Client::new(rn.create_client(client_name.to_owned())); rn.enable(client_name, true); rn.connect(client_name, server_name); let reply = block_on(async { client.ping(&Echo { x: 777 }).await.unwrap() }); assert_eq!(reply, Echo { x: 777 }); println!("{:?}", reply); } ================================================ FILE: courses/dss/labrpc/src/client.rs ================================================ use std::fmt; use std::sync::{Arc, Mutex}; use futures::channel::mpsc::UnboundedSender; use futures::channel::oneshot; use futures::executor::ThreadPool; use futures::future::{self, FutureExt}; use crate::error::{Error, Result}; use crate::server::RpcFuture; pub struct Rpc { pub(crate) client_name: String, pub(crate) fq_name: &'static str, pub(crate) req: Option>, pub(crate) resp: Option>>>, pub(crate) hooks: Arc>>>, } impl Rpc { pub(crate) fn take_resp_sender(&mut self) -> Option>>> { self.resp.take() } } impl fmt::Debug for Rpc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Rpc") .field("client_name", &self.client_name) .field("fq_name", &self.fq_name) .finish() } } pub trait RpcHooks: Sync + Send + 'static { fn before_dispatch(&self, fq_name: &str, req: &[u8]) -> Result<()>; fn after_dispatch(&self, fq_name: &str, resp: Result>) -> Result>; } #[derive(Clone)] pub struct Client { // this end-point's name pub(crate) name: String, // copy of Network.sender pub(crate) sender: UnboundedSender, pub(crate) hooks: Arc>>>, pub worker: ThreadPool, } impl Client { pub fn call(&self, fq_name: &'static str, req: &Req) -> RpcFuture> where Req: labcodec::Message, Rsp: labcodec::Message + 'static, { let mut buf = vec![]; if let Err(e) = labcodec::encode(req, &mut buf) { return Box::pin(future::err(Error::Encode(e))); } let (tx, rx) = oneshot::channel(); let rpc = Rpc { client_name: self.name.clone(), fq_name, req: Some(buf), resp: Some(tx), hooks: self.hooks.clone(), }; // Sends requests and waits responses. if self.sender.unbounded_send(rpc).is_err() { return Box::pin(future::err(Error::Stopped)); } Box::pin(rx.then(|res| async move { match res { Ok(Ok(resp)) => labcodec::decode(&resp).map_err(Error::Decode), Ok(Err(e)) => Err(e), Err(e) => Err(Error::Recv(e)), } })) } pub fn set_hooks(&self, hooks: Arc) { *self.hooks.lock().unwrap() = Some(hooks); } pub fn clear_hooks(&self) { *self.hooks.lock().unwrap() = None; } } ================================================ FILE: courses/dss/labrpc/src/error.rs ================================================ use std::{error, fmt, result}; use futures::channel::oneshot::Canceled; use labcodec::{DecodeError, EncodeError}; #[derive(Clone, Debug, PartialEq, Eq)] pub enum Error { Unimplemented(String), Encode(EncodeError), Decode(DecodeError), Recv(Canceled), Timeout, Stopped, Other(String), } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:?}", self) } } impl error::Error for Error { fn source(&self) -> Option<&(dyn error::Error + 'static)> { match *self { Error::Encode(ref e) => Some(e), Error::Decode(ref e) => Some(e), Error::Recv(ref e) => Some(e), _ => None, } } } pub type Result = result::Result; ================================================ FILE: courses/dss/labrpc/src/lib.rs ================================================ #![allow(clippy::new_without_default)] mod client; mod error; #[macro_use] mod macros; mod network; mod server; pub use self::client::{Client, Rpc, RpcHooks}; pub use self::error::{Error, Result}; pub use self::network::Network; pub use self::server::{Handler, HandlerFactory, RpcFuture, Server, ServerBuilder}; #[cfg(test)] pub mod tests { use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{mpsc, Arc, Mutex, Once}; use std::thread; use std::time::{Duration, Instant}; use futures::channel::oneshot::Canceled; use futures::executor::{block_on, ThreadPool}; use futures::stream::StreamExt; use futures_timer::Delay; use prost_derive::Message; use super::*; service! { /// A simple test-purpose service. service junk { /// Doc comments. rpc handler2(JunkArgs) returns (JunkReply); rpc handler3(JunkArgs) returns (JunkReply); rpc handler4(JunkArgs) returns (JunkReply); } } use junk::{add_service, Client as JunkClient, Service as Junk}; // Hand-written protobuf messages. #[derive(Clone, PartialEq, Message)] pub struct JunkArgs { #[prost(int64, tag = "1")] pub x: i64, } #[derive(Clone, PartialEq, Message)] pub struct JunkReply { #[prost(string, tag = "1")] pub x: String, } #[derive(Default)] struct JunkInner { log2: Vec, } #[derive(Clone)] struct JunkService { inner: Arc>, } impl JunkService { fn new() -> JunkService { JunkService { inner: Arc::default(), } } } #[async_trait::async_trait] impl Junk for JunkService { async fn handler2(&self, args: JunkArgs) -> Result { self.inner.lock().unwrap().log2.push(args.x); Ok(JunkReply { x: format!("handler2-{}", args.x), }) } async fn handler3(&self, args: JunkArgs) -> Result { Delay::new(Duration::from_secs(20)).await; Ok(JunkReply { x: format!("handler3-{}", -args.x), }) } async fn handler4(&self, _: JunkArgs) -> Result { Ok(JunkReply { x: "pointer".to_owned(), }) } } fn init_logger() { static LOGGER_INIT: Once = Once::new(); LOGGER_INIT.call_once(env_logger::init); } #[test] fn test_service_dispatch() { init_logger(); let mut builder = ServerBuilder::new("test".to_owned()); let junk = JunkService::new(); add_service(junk.clone(), &mut builder).unwrap(); let prev_len = builder.services.len(); add_service(junk, &mut builder).unwrap_err(); assert_eq!(builder.services.len(), prev_len); let server = builder.build(); let buf = block_on(async { server.dispatch("junk.handler4", &[]).await.unwrap() }); let rsp = labcodec::decode(&buf).unwrap(); assert_eq!( JunkReply { x: "pointer".to_owned(), }, rsp, ); block_on(async { server .dispatch("junk.handler4", b"bad message") .await .unwrap_err(); server.dispatch("badjunk.handler4", &[]).await.unwrap_err(); server.dispatch("junk.badhandler", &[]).await.unwrap_err(); }); } #[test] fn test_network_client_rpc() { init_logger(); let mut builder = ServerBuilder::new("test".to_owned()); let junk = JunkService::new(); add_service(junk, &mut builder).unwrap(); let server = builder.build(); let (net, incoming) = Network::create(); net.add_server(server); let client = JunkClient::new(net.create_client("test_client".to_owned())); let (tx, rx) = mpsc::channel(); let cli = client.clone(); client.spawn(async move { let reply = cli.handler4(&JunkArgs { x: 777 }).await; tx.send(reply).unwrap(); }); let (mut rpc, incoming) = block_on(async { match incoming.into_future().await { (Some(rpc), s) => (rpc, s), _ => panic!("unexpected error"), } }); let reply = JunkReply { x: "boom!!!".to_owned(), }; let mut buf = vec![]; labcodec::encode(&reply, &mut buf).unwrap(); let resp = rpc.take_resp_sender().unwrap(); resp.send(Ok(buf)).unwrap(); assert_eq!(rpc.client_name, "test_client"); assert_eq!(rpc.fq_name, "junk.handler4"); assert!(!rpc.req.as_ref().unwrap().is_empty()); assert_eq!(rx.recv().unwrap(), Ok(reply)); let (tx, rx) = mpsc::channel(); let cli = client.clone(); client.spawn(async move { let reply = cli.handler4(&JunkArgs { x: 777 }).await; tx.send(reply).unwrap(); }); let (rpc, incoming) = block_on(async { match incoming.into_future().await { (Some(rpc), s) => (rpc, s), _ => panic!("unexpected error"), } }); drop(rpc.resp); assert_eq!(rx.recv().unwrap(), Err(Error::Recv(Canceled))); drop(incoming); assert_eq!( block_on(async { client.handler4(&JunkArgs::default()).await }), Err(Error::Stopped) ); } fn junk_suit() -> (Network, Server, JunkService) { let net = Network::new(); let server_name = "test_server".to_owned(); let mut builder = ServerBuilder::new(server_name); let junk_server = JunkService::new(); add_service(junk_server.clone(), &mut builder).unwrap(); let server = builder.build(); net.add_server(server.clone()); (net, server, junk_server) } #[test] fn test_basic() { init_logger(); let (net, _, _) = junk_suit(); let client = JunkClient::new(net.create_client("test_client".to_owned())); net.connect("test_client", "test_server"); net.enable("test_client", true); let rsp = block_on(async { client.handler4(&JunkArgs::default()).await.unwrap() }); assert_eq!( JunkReply { x: "pointer".to_owned(), }, rsp, ); } // does net.Enable(endname, false) really disconnect a client? #[test] fn test_disconnect() { init_logger(); let (net, _, _) = junk_suit(); let client = JunkClient::new(net.create_client("test_client".to_owned())); net.connect("test_client", "test_server"); block_on(async { client.handler4(&JunkArgs::default()).await.unwrap_err() }); net.enable("test_client", true); let rsp = block_on(async { client.handler4(&JunkArgs::default()).await.unwrap() }); assert_eq!( JunkReply { x: "pointer".to_owned(), }, rsp, ); } // test net.GetCount() #[test] fn test_count() { init_logger(); let (net, _, _) = junk_suit(); let client = JunkClient::new(net.create_client("test_client".to_owned())); net.connect("test_client", "test_server"); net.enable("test_client", true); for i in 0..=16 { let reply = block_on(async { client.handler2(&JunkArgs { x: i }).await.unwrap() }); assert_eq!(reply.x, format!("handler2-{}", i)); } assert_eq!(net.count("test_server"), 17); } // test RPCs from concurrent Clients #[test] fn test_concurrent_many() { init_logger(); let (net, server, _) = junk_suit(); let server_name = server.name(); let pool = ThreadPool::new().unwrap(); let (tx, rx) = mpsc::channel::(); let nclients = 20usize; let nrpcs = 10usize; for i in 0..nclients { let net = net.clone(); let sender = tx.clone(); let server_name = server_name.to_string(); pool.spawn_ok(async move { let mut n = 0; let client_name = format!("client-{}", i); let client = JunkClient::new(net.create_client(client_name.clone())); net.enable(&client_name, true); net.connect(&client_name, &server_name); for j in 0..nrpcs { let x = (i * 100 + j) as i64; let reply = client.handler2(&JunkArgs { x }).await.unwrap(); assert_eq!(reply.x, format!("handler2-{}", x)); n += 1; } sender.send(n).unwrap(); }); } let mut total = 0; for _ in 0..nclients { total += rx.recv().unwrap(); } assert_eq!(total, nrpcs * nclients); let n = net.count(server_name); assert_eq!(n, total); } #[test] fn test_unreliable() { init_logger(); let (net, server, _) = junk_suit(); let server_name = server.name(); net.set_reliable(false); let pool = ThreadPool::new().unwrap(); let (tx, rx) = mpsc::channel::(); let nclients = 300; for i in 0..nclients { let sender = tx.clone(); let mut n = 0; let server_name = server_name.to_owned(); let net = net.clone(); pool.spawn_ok(async move { let client_name = format!("client-{}", i); let client = JunkClient::new(net.create_client(client_name.clone())); net.enable(&client_name, true); net.connect(&client_name, &server_name); let x = i * 100; if let Ok(reply) = client.handler2(&JunkArgs { x }).await { assert_eq!(reply.x, format!("handler2-{}", x)); n += 1; } sender.send(n).unwrap(); }); } let mut total = 0; for _ in 0..nclients { total += rx.recv().unwrap(); } assert!( !(total == nclients as _ || total == 0), "all RPCs succeeded despite unreliable total {}, nclients {}", total, nclients ); } // test concurrent RPCs from a single Client #[test] fn test_concurrent_one() { init_logger(); let (net, server, junk_server) = junk_suit(); let server_name = server.name(); let pool = ThreadPool::new().unwrap(); let (tx, rx) = mpsc::channel::(); let nrpcs = 20; for i in 0..20 { let sender = tx.clone(); let client_name = format!("client-{}", i); let client = JunkClient::new(net.create_client(client_name.clone())); net.enable(&client_name, true); net.connect(&client_name, server_name); pool.spawn_ok(async move { let mut n = 0; let x = i + 100; let reply = client.handler2(&JunkArgs { x }).await.unwrap(); assert_eq!(reply.x, format!("handler2-{}", x)); n += 1; sender.send(n).unwrap() }); } let mut total = 0; for _ in 0..nrpcs { total += rx.recv().unwrap(); } assert_eq!( total, nrpcs, "wrong number of RPCs completed, got {}, expected {}", total, nrpcs ); assert_eq!( junk_server.inner.lock().unwrap().log2.len(), nrpcs, "wrong number of RPCs delivered" ); let n = net.count(server.name()); assert_eq!(n, total, "wrong count() {}, expected {}", n, total); } // regression: an RPC that's delayed during Enabled=false // should not delay subsequent RPCs (e.g. after Enabled=true). #[test] fn test_regression1() { init_logger(); let (net, server, junk_server) = junk_suit(); let server_name = server.name(); let client_name = "client"; let client = JunkClient::new(net.create_client(client_name.to_owned())); net.connect(client_name, server_name); // start some RPCs while the Client is disabled. // they'll be delayed. net.enable(client_name, false); let pool = ThreadPool::new().unwrap(); let (tx, rx) = mpsc::channel::(); let nrpcs = 20; for i in 0..20 { let sender = tx.clone(); let cli = client.clone(); pool.spawn_ok(async move { let x = i + 100; // this call ought to return false. let _ = cli.handler2(&JunkArgs { x }); sender.send(true).unwrap(); }); } // FIXME: have to sleep 300ms to pass the test // in my computer (i5-4200U, 4 threads). thread::sleep(Duration::from_millis(100 * 3)); let t0 = Instant::now(); net.enable(client_name, true); let x = 99; let reply = block_on(async { client.handler2(&JunkArgs { x }).await.unwrap() }); assert_eq!(reply.x, format!("handler2-{}", x)); let dur = t0.elapsed(); assert!( dur < Duration::from_millis(30), "RPC took too long ({:?}) after Enable", dur ); for _ in 0..nrpcs { rx.recv().unwrap(); } let len = junk_server.inner.lock().unwrap().log2.len(); assert_eq!( len, 1, "wrong number ({}) of RPCs delivered, expected 1", len ); let n = net.count(server.name()); assert_eq!(n, 1, "wrong count() {}, expected 1", n); } // if an RPC is stuck in a server, and the server // is killed with DeleteServer(), does the RPC // get un-stuck? #[test] fn test_killed() { init_logger(); let (net, server, _junk_server) = junk_suit(); let server_name = server.name(); let client_name = "client"; let client = JunkClient::new(net.create_client(client_name.to_owned())); net.connect(client_name, server_name); net.enable(client_name, true); let (tx, rx) = mpsc::channel(); let cli = client.clone(); client.spawn(async move { let reply = cli.handler3(&JunkArgs { x: 99 }).await; tx.send(reply).unwrap(); }); thread::sleep(Duration::from_secs(1)); rx.recv_timeout(Duration::from_millis(100)).unwrap_err(); net.delete_server(server_name); let reply = rx.recv_timeout(Duration::from_millis(100)).unwrap(); assert_eq!(reply, Err(Error::Stopped)); } struct Hooks { drop_req: AtomicBool, drop_resp: AtomicBool, } impl RpcHooks for Hooks { fn before_dispatch(&self, _: &str, _: &[u8]) -> Result<()> { if self.drop_req.load(Ordering::Relaxed) { Err(Error::Other("reqhook".to_owned())) } else { Ok(()) } } fn after_dispatch(&self, _: &str, resp: Result>) -> Result> { if self.drop_resp.load(Ordering::Relaxed) { Err(Error::Other("resphook".to_owned())) } else { resp } } } #[test] fn test_rpc_hooks() { init_logger(); let (net, _, _) = junk_suit(); let raw_cli = net.create_client("test_client".to_owned()); let hook = Arc::new(Hooks { drop_req: AtomicBool::new(false), drop_resp: AtomicBool::new(false), }); raw_cli.set_hooks(hook.clone()); let client = JunkClient::new(raw_cli); net.connect("test_client", "test_server"); net.enable("test_client", true); let i = 100; let reply = block_on(async { client.handler2(&JunkArgs { x: i }).await.unwrap() }); assert_eq!(reply.x, format!("handler2-{}", i)); hook.drop_req.store(true, Ordering::Relaxed); assert_eq!( block_on(async { client.handler2(&JunkArgs { x: i }).await.unwrap_err() }), Error::Other("reqhook".to_owned()) ); hook.drop_req.store(false, Ordering::Relaxed); hook.drop_resp.store(true, Ordering::Relaxed); assert_eq!( block_on(async { client.handler2(&JunkArgs { x: i }).await.unwrap_err() }), Error::Other("resphook".to_owned()) ); hook.drop_resp.store(false, Ordering::Relaxed); block_on(async { client.handler2(&JunkArgs { x: i }).await.unwrap() }); assert_eq!(reply.x, format!("handler2-{}", i)); } } ================================================ FILE: courses/dss/labrpc/src/macros.rs ================================================ #[macro_export] macro_rules! service { () => { compile_error!("empty service is not allowed"); }; ( $(#[$service_attr:meta])* service $svc_name:ident { $( $(#[$method_attr:meta])* rpc $method_name:ident($input:ty) returns ($output:ty); )* } ) => { $(#[$service_attr])* pub mod $svc_name { // In order to find input and output. use super::*; // $( use super::$input; )* // $( use super::$output;)* extern crate futures as __futures; #[async_trait::async_trait] pub trait Service: Clone + Send + 'static { $( $(#[$method_attr])* async fn $method_name(&self, req: $input) -> $crate::Result<$output>; )* } #[derive(Clone)] pub struct Client { client: $crate::Client, } impl Client { pub fn new(client: $crate::Client) -> Client { Client { client } } pub fn spawn(&self, f: F) where F: __futures::Future + Send + 'static { self.client.worker.spawn_ok(f); } $(pub fn $method_name(&self, args: &$input) -> $crate::RpcFuture<$crate::Result<$output>> { let fq_name = concat!(stringify!($svc_name), ".", stringify!($method_name)); self.client.call(fq_name, args) })* } pub fn add_service(svc: T, builder: &mut $crate::ServerBuilder) -> $crate::Result<()> { use ::std::sync::Mutex; struct Factory { svc: Mutex, } impl $crate::HandlerFactory for Factory { fn handler(&self, name: &'static str) -> Box<$crate::Handler> { let s = self.svc.lock().unwrap().clone(); Box::new(move |req| { match name { $(stringify!($method_name) => { let request = match labcodec::decode(req) { Ok(req) => req, Err(e) => return Box::pin(__futures::future::err( $crate::Error::Decode(e) )), }; Box::pin(async move { let f = s.$method_name(request); let resp = f.await; match resp { Ok(resp) => { let mut rsp = vec![]; labcodec::encode(&resp, &mut rsp).map_err($crate::Error::Encode)?; Ok(rsp) } Err(e) => Err(e), } }) })* other => { Box::pin(__futures::future::err( $crate::Error::Unimplemented( format!("unknown {} in {}", other, stringify!($svc_name)) ) )) } } }) } } let fact = Factory { svc: Mutex::new(svc), }; builder.add_service(stringify!($svc_name), Box::new(fact)) } } }; } ================================================ FILE: courses/dss/labrpc/src/network.rs ================================================ use std::collections::HashMap; use std::future::Future; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use std::sync::{Arc, Mutex}; use std::time::Duration; use futures::channel::mpsc::{unbounded, UnboundedReceiver, UnboundedSender}; use futures::executor::ThreadPool; use futures::future::FutureExt; use futures::select; use futures::stream::StreamExt; use futures_timer::Delay; use log::{debug, error}; use rand::{thread_rng, Rng}; use crate::client::{Client, Rpc}; use crate::error::{Error, Result}; use crate::server::Server; #[derive(Debug)] struct EndInfo { enabled: bool, reliable: bool, long_reordering: bool, server: Option, } struct Endpoints { // by client name enabled: HashMap, // servers, by name servers: HashMap>, // client_name -> server_name connections: HashMap>, } struct NetworkCore { reliable: AtomicBool, // pause a long time on send on disabled connection long_delays: AtomicBool, // sometimes delay replies a long time long_reordering: AtomicBool, endpoints: Mutex, count: AtomicUsize, sender: UnboundedSender, poller: ThreadPool, worker: ThreadPool, } #[derive(Clone)] pub struct Network { core: Arc, } impl Network { pub fn new() -> Network { let (net, incoming) = Network::create(); net.start(incoming); net } pub fn create() -> (Network, UnboundedReceiver) { let (sender, incoming) = unbounded(); let net = Network { core: Arc::new(NetworkCore { reliable: AtomicBool::new(true), long_delays: AtomicBool::new(false), long_reordering: AtomicBool::new(false), endpoints: Mutex::new(Endpoints { enabled: HashMap::new(), servers: HashMap::new(), connections: HashMap::new(), }), count: AtomicUsize::new(0), poller: ThreadPool::builder().pool_size(2).create().unwrap(), worker: ThreadPool::new().unwrap(), sender, }), }; (net, incoming) } fn start(&self, mut incoming: UnboundedReceiver) { let network = self.clone(); self.core.poller.spawn_ok(async move { while let Some(mut rpc) = incoming.next().await { let resp = rpc.take_resp_sender().unwrap(); let net = network.clone(); network.core.poller.spawn_ok(async move { let res = net.process_rpc(rpc).await; if let Err(e) = resp.send(res) { error!("fail to send resp: {:?}", e); } }) } }); } pub fn add_server(&self, server: Server) { let mut eps = self.core.endpoints.lock().unwrap(); eps.servers.insert(server.core.name.clone(), Some(server)); } pub fn delete_server(&self, name: &str) { let mut eps = self.core.endpoints.lock().unwrap(); if let Some(s) = eps.servers.get_mut(name) { *s = None; } } pub fn create_client(&self, name: String) -> Client { let sender = self.core.sender.clone(); let mut eps = self.core.endpoints.lock().unwrap(); eps.enabled.insert(name.clone(), false); eps.connections.insert(name.clone(), None); Client { name, sender, worker: self.core.worker.clone(), hooks: Arc::new(Mutex::new(None)), } } /// Connects a Client to a server. /// a Client can only be connected once in its lifetime. pub fn connect(&self, client_name: &str, server_name: &str) { let mut eps = self.core.endpoints.lock().unwrap(); eps.connections .insert(client_name.to_owned(), Some(server_name.to_owned())); } /// Enable/disable a Client. pub fn enable(&self, client_name: &str, enabled: bool) { debug!( "client {} is {}", client_name, if enabled { "enabled" } else { "disabled" } ); let mut eps = self.core.endpoints.lock().unwrap(); eps.enabled.insert(client_name.to_owned(), enabled); } pub fn set_reliable(&self, yes: bool) { self.core.reliable.store(yes, Ordering::Release); } pub fn set_long_reordering(&self, yes: bool) { self.core.long_reordering.store(yes, Ordering::Release); } pub fn set_long_delays(&self, yes: bool) { self.core.long_delays.store(yes, Ordering::Release); } pub fn count(&self, server_name: &str) -> usize { let eps = self.core.endpoints.lock().unwrap(); eps.servers[server_name].as_ref().unwrap().count() } pub fn total_count(&self) -> usize { self.core.count.load(Ordering::Relaxed) } fn end_info(&self, client_name: &str) -> EndInfo { let eps = self.core.endpoints.lock().unwrap(); let mut server = None; if let Some(Some(server_name)) = eps.connections.get(client_name) { server = eps.servers[server_name].clone(); } EndInfo { enabled: eps.enabled[client_name], reliable: self.core.reliable.load(Ordering::Acquire), long_reordering: self.core.long_reordering.load(Ordering::Acquire), server, } } fn is_server_dead(&self, client_name: &str, server_name: &str, server_id: usize) -> bool { let eps = self.core.endpoints.lock().unwrap(); !eps.enabled[client_name] || eps.servers.get(server_name).map_or(true, |o| { o.as_ref().map(|s| s.core.id != server_id).unwrap_or(true) }) } async fn process_rpc(&self, rpc: Rpc) -> Result> { self.core.count.fetch_add(1, Ordering::Relaxed); let network = self.clone(); let end_info = self.end_info(&rpc.client_name); debug!("{:?} process with {:?}", rpc, end_info); let EndInfo { enabled, reliable, long_reordering, server, } = end_info; match (enabled, server) { (true, Some(server)) => { let short_delay = if !reliable { // short delay let ms = thread_rng().gen::() % 27; Some(ms) } else { None }; if !reliable && (thread_rng().gen::() % 1000) < 100 { // drop the request, return as if timeout Delay::new(Duration::from_secs(short_delay.unwrap())).await; return Err(Error::Timeout); } let drop_reply = !reliable && thread_rng().gen::() % 1000 < 100; let long_reordering = if long_reordering && thread_rng().gen_range(0, 900) < 600i32 { // delay the response for a while let upper_bound: u64 = 1 + thread_rng().gen_range(0, 2000); Some(200 + thread_rng().gen_range(0, upper_bound)) } else { None }; // Dispatch process_rpc( short_delay, drop_reply, long_reordering, rpc, network, server, ) .await } _ => { // simulate no reply and eventual timeout. let ms = if self.core.long_delays.load(Ordering::Acquire) { // let Raft tests check that leader doesn't send // RPCs synchronously. thread_rng().gen::() % 7000 } else { // many kv tests require the client to try each // server in fairly rapid succession. thread_rng().gen::() % 100 }; debug!("{:?} delay {}ms then timeout", rpc, ms); Delay::new(Duration::from_millis(ms)).await; Err(Error::Timeout) } } } /// Spawns a future to run on this net framework. pub fn spawn(&self, f: F) where F: Future + Send + 'static, { self.core.worker.spawn_ok(f); } /// Spawns a future to run on this net framework. pub fn spawn_poller(&self, f: F) where F: Future + Send + 'static, { self.core.poller.spawn_ok(f); } } async fn process_rpc( mut delay: Option, drop_reply: bool, long_reordering: Option, mut rpc: Rpc, network: Network, server: Server, ) -> Result> { // Dispatch =============================================================== if let Some(delay) = delay { Delay::new(Duration::from_millis(delay)).await; } // We has finished the delay, take it out to prevent polling // twice. delay.take(); let fq_name = rpc.fq_name; let req = rpc.req.take().unwrap(); if let Some(hooks) = rpc.hooks.lock().unwrap().as_ref() { hooks.before_dispatch(fq_name, &req)?; } // Execute the request (call the RPC handler) in a separate thread so that // we can periodically check if the server has been killed and the RPC // should get a failure reply. // // do not reply if DeleteServer() has been called, i.e. the server has been killed. // this is needed to avoid situation in which a client gets a positive reply // to an Append, but the server persisted the update into the old Persister. // config.go is careful to call DeleteServer() before superseding the Persister. let resp = select! { res = server.dispatch(fq_name, &req).fuse() => res, _ = server_dead( Duration::from_millis(100), network.clone(), &rpc.client_name, &server.core.name, server.core.id, ).fuse() => Err(Error::Stopped), }; let resp = if let Some(hooks) = rpc.hooks.lock().unwrap().as_ref() { hooks.after_dispatch(fq_name, resp)? } else { resp? }; // Ongoing ================================================================ let client_name = &rpc.client_name; let server_name = &server.core.name; let server_id = server.core.id; if network.is_server_dead(client_name, server_name, server_id) { return Err(Error::Stopped); } if drop_reply { // drop the reply, return as if timeout. return Err(Error::Timeout); } // Reordering ============================================================= if let Some(reordering) = long_reordering { debug!("{:?} next long reordering {}ms", rpc, reordering); Delay::new(Duration::from_millis(reordering)).await; Ok(resp) } else { Ok(resp) } } /// Checks if the specified server killed. /// /// It will return when the server is killed. async fn server_dead( interval: Duration, net: Network, client_name: &str, server_name: &str, server_id: usize, ) { loop { Delay::new(interval).await; if net.is_server_dead(client_name, server_name, server_id) { debug!("{:?} is dead", server_name); return; } } } ================================================ FILE: courses/dss/labrpc/src/server.rs ================================================ use std::collections::hash_map::{Entry, HashMap}; use std::fmt; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use futures::future::{self, BoxFuture}; use crate::error::{Error, Result}; static ID_ALLOC: AtomicUsize = AtomicUsize::new(0); pub type RpcFuture = BoxFuture<'static, T>; pub type Handler = dyn FnOnce(&[u8]) -> RpcFuture>>; pub trait HandlerFactory: Sync + Send + 'static { fn handler(&self, name: &'static str) -> Box; } pub struct ServerBuilder { name: String, // Service name -> service methods pub(crate) services: HashMap<&'static str, Box>, } impl ServerBuilder { pub fn new(name: String) -> ServerBuilder { ServerBuilder { name, services: HashMap::new(), } } pub fn add_service( &mut self, service_name: &'static str, factory: Box, ) -> Result<()> { match self.services.entry(service_name) { Entry::Occupied(_) => Err(Error::Other(format!( "{} has already registered", service_name ))), Entry::Vacant(entry) => { entry.insert(factory); Ok(()) } } } pub fn build(self) -> Server { Server { core: Arc::new(ServerCore { name: self.name, services: self.services, id: ID_ALLOC.fetch_add(1, Ordering::Relaxed), count: AtomicUsize::new(0), }), } } } pub(crate) struct ServerCore { pub(crate) name: String, pub(crate) id: usize, pub(crate) services: HashMap<&'static str, Box>, pub(crate) count: AtomicUsize, } #[derive(Clone)] pub struct Server { pub(crate) core: Arc, } impl Server { pub fn count(&self) -> usize { self.core.count.load(Ordering::Relaxed) } pub fn name(&self) -> &str { &self.core.name } pub(crate) fn dispatch(&self, fq_name: &'static str, req: &[u8]) -> RpcFuture>> { self.core.count.fetch_add(1, Ordering::Relaxed); let mut names = fq_name.split('.'); let service_name = match names.next() { Some(n) => n, None => { return Box::pin(future::err(Error::Unimplemented(format!( "unknown {}", fq_name )))); } }; let method_name = match names.next() { Some(n) => n, None => { return Box::pin(future::err(Error::Unimplemented(format!( "unknown {}", fq_name )))); } }; if let Some(factory) = self.core.services.get(service_name) { let handle = factory.handler(method_name); handle(req) } else { Box::pin(future::err(Error::Unimplemented(format!( "unknown {}", fq_name )))) } } } impl fmt::Debug for Server { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Server") .field("name", &self.core.name) .field("id", &self.core.id) .finish() } } ================================================ FILE: courses/dss/linearizability/Cargo.toml ================================================ [package] name = "linearizability" version = "0.1.0" edition = "2018" publish = false [dev-dependencies] regex = "1.3" lazy_static = "1.4" ================================================ FILE: courses/dss/linearizability/src/bitset.rs ================================================ use std::num::Wrapping; #[derive(Clone)] pub struct Bitset(Vec); impl Bitset { pub fn new(bits: usize) -> Self { let extra = if bits % 64 != 0 { 1 } else { 0 }; Bitset(vec![0; bits / 64 + extra]) } pub fn set(&mut self, pos: usize) { let (major, minor) = bitset_index(pos); self.0[major] |= 1 << minor; } pub fn clear(&mut self, pos: usize) { let (major, minor) = bitset_index(pos); self.0[major] &= !(1 << minor); } fn popcnt(&self) -> usize { let mut total = 0; for b in &self.0 { let mut v = *b; v = (v & 0x5555_5555_5555_5555) + ((v & 0xAAAA_AAAA_AAAA_AAAA) >> 1); v = (v & 0x3333_3333_3333_3333) + ((v & 0xCCCC_CCCC_CCCC_CCCC) >> 2); v = (v & 0x0F0F_0F0F_0F0F_0F0F) + ((v & 0xF0F0_F0F0_F0F0_F0F0) >> 4); v = (Wrapping(v) * Wrapping(0x0101_0101_0101_0101)).0; total += ((v >> 56) & 0xFF) as usize; } total } pub fn hash(&self) -> u64 { let mut hash = self.popcnt() as u64; for v in &self.0 { hash ^= v; } hash } pub fn equals(&self, b2: &Bitset) -> bool { let b = &self.0; let b2 = &b2.0; if b.len() != b2.len() { return false; } for i in 0..b.len() { if b[i] != b2[i] { return false; } } true } } fn bitset_index(pos: usize) -> (usize, usize) { (pos / 64, pos % 64) } ================================================ FILE: courses/dss/linearizability/src/lib.rs ================================================ mod bitset; pub mod model; pub mod models; use std::cell::{Ref, RefCell}; use std::collections::HashMap; use std::fmt::Debug; use std::rc::Rc; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc::{channel, Receiver, RecvTimeoutError}; use std::sync::Arc; use std::thread; use std::time::Duration; use crate::bitset::Bitset; use crate::model::{Event, EventKind, Events, Model, Operations, Value}; enum EntryKind { CallEntry, ReturnEntry, } struct Entry { pub kind: EntryKind, pub value: T, pub id: usize, pub time: i64, } fn make_entries(history: Operations) -> Vec>> { let mut entries = Vec::new(); for (id, elem) in history.into_iter().enumerate() { entries.push(Entry { kind: EntryKind::CallEntry, value: Value::Input(elem.input), id, time: elem.call, }); entries.push(Entry { kind: EntryKind::ReturnEntry, value: Value::Output(elem.output), id, time: elem.finish, }) } entries.sort_by(|a, b| a.time.partial_cmp(&b.time).unwrap()); entries } struct LinkedNodes { head: Option>, } impl LinkedNodes { pub fn new() -> Self { LinkedNodes { head: None } } pub fn head(&self) -> Option> { self.head.clone() } pub fn from_entries(entries: Vec>) -> Self { let mut matches: HashMap> = HashMap::new(); let mut nodes = Self::new(); for entry in entries.into_iter().rev() { nodes.push_front(match entry.kind { EntryKind::CallEntry => Rc::new(RefCell::new(Node { value: entry.value, matched: matches.get(&entry.id).cloned(), id: entry.id, next: None, prev: None, })), EntryKind::ReturnEntry => { let node = Rc::new(RefCell::new(Node { value: entry.value, matched: None, id: entry.id, next: None, prev: None, })); matches.insert(entry.id, node.clone()); node } }) } nodes } pub fn len(&self) -> usize { let mut len = 0; let mut entry = self.head.clone(); while let Some(e) = entry { entry = e.borrow().next.clone(); len += 1; } len } pub fn push_front(&mut self, new_head: LinkNode) { match self.head.take() { Some(old_head) => { old_head.borrow_mut().prev = Some(new_head.clone()); new_head.borrow_mut().next = Some(old_head); self.head = Some(new_head); } None => { self.head = Some(new_head); } } } } type LinkNode = Rc>>; struct Node { pub value: T, pub matched: Option>, pub id: usize, pub next: Option>, pub prev: Option>, } fn renumber(events: Vec>) -> Vec> { let mut e = Vec::new(); let mut m: HashMap = HashMap::new(); // renumbering let mut id: usize = 0; for event in events { e.push(Event { kind: event.kind, value: event.value, id: *m.entry(event.id).or_insert_with(|| { id += 1; id - 1 }), }); } e } fn convert_entries(events: Vec>) -> Vec> { let mut entries = Vec::new(); for event in events { entries.push(match event.kind { EventKind::CallEvent => Entry { kind: EntryKind::CallEntry, value: event.value, id: event.id, time: -1, }, EventKind::ReturnEvent => Entry { kind: EntryKind::ReturnEntry, value: event.value, id: event.id, time: -1, }, }) } entries } struct CacheEntry { linearized: Bitset, state: T, } fn cache_contains( model: &M, cache: &HashMap>>, entry: &CacheEntry, ) -> bool { if cache.contains_key(&entry.linearized.hash()) { for elem in &cache[&entry.linearized.hash()] { if entry.linearized.equals(&elem.linearized) && model.equal(&entry.state, &elem.state) { return true; } } } false } struct CallsEntry { entry: Option>, state: T, } fn lift(entry: &LinkNode) { let prev = Ref::map(entry.borrow(), |e| e.prev.as_ref().unwrap()); prev.borrow_mut().next = entry.borrow().next.clone(); let next = Ref::map(entry.borrow(), |e| e.next.as_ref().unwrap()); next.borrow_mut().prev = entry.borrow().prev.clone(); let matched = Ref::map(entry.borrow(), |e| e.matched.as_ref().unwrap()); let matched_prev = Ref::map(matched.borrow(), |e| e.prev.as_ref().unwrap()); matched_prev.borrow_mut().next = matched.borrow().next.clone(); if matched.borrow().next.is_some() { let matched_next = Ref::map(matched.borrow(), |e| e.next.as_ref().unwrap()); matched_next.borrow_mut().prev = matched.borrow().prev.clone(); } } fn unlift(entry: &LinkNode) { { let matched = Ref::map(entry.borrow(), |e| e.matched.as_ref().unwrap()); let matched_prev = Ref::map(matched.borrow(), |e| e.prev.as_ref().unwrap()); matched_prev.borrow_mut().next = Some(matched.clone()); if matched.borrow().next.is_some() { let matched_next = Ref::map(matched.borrow(), |e| e.next.as_ref().unwrap()); matched_next.borrow_mut().prev = Some(matched.clone()); } } let prev = Ref::map(entry.borrow(), |e| e.prev.as_ref().unwrap()); prev.borrow_mut().next = Some(entry.clone()); let next = Ref::map(entry.borrow(), |e| e.next.as_ref().unwrap()); next.borrow_mut().prev = Some(entry.clone()); } fn check_single( model: M, mut subhistory: LinkedNodes>, kill: Arc, ) -> bool { let n = subhistory.len() / 2; let mut linearized = Bitset::new(n); let mut cache = HashMap::new(); let mut calls = vec![]; let mut state = model.init(); subhistory.push_front(Rc::new(RefCell::new(Node { value: Value::None, matched: None, id: usize::max_value(), prev: None, next: None, }))); let head_entry = subhistory.head().unwrap(); let mut entry = head_entry.borrow().next.clone(); while head_entry.borrow().next.is_some() { if kill.load(Ordering::SeqCst) { return false; } let matched = entry.as_ref().unwrap().borrow().matched.clone(); entry = if let Some(matching) = matched { // the return entry let res = model.step( &state, entry.as_ref().unwrap().borrow().value.input(), matching.borrow().value.output(), ); match res { (true, new_state) => { let mut new_linearized = linearized.clone(); new_linearized.set(entry.as_ref().unwrap().borrow().id); let new_cache_entry = CacheEntry { linearized: new_linearized.clone(), state: new_state.clone(), }; if !cache_contains(&model, &cache, &new_cache_entry) { let hash = new_linearized.hash(); cache.entry(hash).or_default().push(new_cache_entry); calls.push(CallsEntry { entry: entry.clone(), state, }); state = new_state; linearized.set(entry.as_ref().unwrap().borrow().id); lift(entry.as_ref().unwrap()); head_entry.borrow().next.clone() } else { entry.as_ref().unwrap().borrow().next.clone() } } (false, _) => entry.as_ref().unwrap().borrow().next.clone(), } } else { if calls.is_empty() { return false; } let calls_top = calls.pop().unwrap(); entry = calls_top.entry; state = calls_top.state; linearized.clear(entry.as_ref().unwrap().borrow().id); unlift(entry.as_ref().unwrap()); entry.as_ref().unwrap().borrow().next.clone() } } true } pub fn check_operations(model: M, history: Operations) -> bool { check_operations_timeout(model, history, Duration::new(0, 0)) } // timeout = 0 means no timeout // if this operation times out, then a false positive is possible pub fn check_operations_timeout( model: M, history: Operations, timeout: Duration, ) -> bool { let partitions = model.partition(history); let (tx, rx) = channel(); let mut handles = vec![]; let kill = Arc::new(AtomicBool::new(false)); let count = partitions.len(); for subhistory in partitions { let tx = tx.clone(); let kill = Arc::clone(&kill); let m = model.clone(); let handle = thread::spawn(move || { let l = LinkedNodes::from_entries(make_entries(subhistory)); let _ = tx.send(check_single(m, l, kill)); }); handles.push(handle); } let res = wait_res(rx, kill, count, timeout); for handle in handles { handle.join().unwrap(); } res } pub fn check_events(model: M, history: Events) -> bool { check_events_timeout(model, history, Duration::new(0, 0)) } // timeout = 0 means no timeout // if this operation times out, then a false positive is possible pub fn check_events_timeout( model: M, history: Events, timeout: Duration, ) -> bool { let partitions = model.partition_event(history); let (tx, rx) = channel(); let mut handles = vec![]; let kill = Arc::new(AtomicBool::new(false)); let count = partitions.len(); for subhistory in partitions { let tx = tx.clone(); let kill = Arc::clone(&kill); let m = model.clone(); let handle = thread::spawn(move || { let l = LinkedNodes::from_entries(convert_entries(renumber(subhistory))); let _ = tx.send(check_single(m, l, kill)); }); handles.push(handle); } let res = wait_res(rx, kill, count, timeout); for handle in handles { handle.join().unwrap(); } res } fn wait_res( rx: Receiver, kill: Arc, mut count: usize, timeout: Duration, ) -> bool { let mut ok = true; loop { match if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 { rx.recv().map_err(From::from) } else { rx.recv_timeout(timeout) } { Ok(res) => { ok = ok && res; if !ok { kill.store(true, Ordering::SeqCst); break; } count -= 1; if count == 0 { break; } } Err(RecvTimeoutError::Timeout) => break, Err(e) => panic!("recv err: {}", e), } } ok } ================================================ FILE: courses/dss/linearizability/src/model.rs ================================================ use std::cmp::PartialEq; use std::fmt::Debug; use std::fmt::Display; use std::marker::Send; #[derive(Debug)] pub enum Value { Input(I), Output(O), None, } impl Value { pub fn input(&self) -> &I { if let Value::Input(i) = self { i } else { panic!("Not a input") } } pub fn output(&self) -> &O { if let Value::Output(o) = self { o } else { panic!("Not a output") } } } #[derive(Debug)] pub struct Operation { pub input: I, pub call: i64, // invocation time pub output: O, pub finish: i64, // response time } pub enum EventKind { CallEvent, ReturnEvent, } pub struct Event { pub kind: EventKind, pub value: T, pub id: usize, } pub type Operations = Vec>; pub type Events = Vec>>; pub trait Model: Clone + Send + 'static { type State: Clone + Display + PartialEq; type Input: Send + Debug + 'static; type Output: Send + Debug + 'static; // Partition functions, such that a history is linearizable if an only // if each partition is linearizable. If you don't want to implement // this, you can always use the `NoPartition` functions implemented // below. fn partition( &self, history: Operations, ) -> Vec> { vec![history] } fn partition_event( &self, history: Events, ) -> Vec> { vec![history] } // Initial state of the system. fn init(&self) -> Self::State; // Step function for the system. Returns whether or not the system // could take this step with the given inputs and outputs and also // returns the new state. This should not mutate the existing state. fn step( &self, state: &Self::State, input: &Self::Input, output: &Self::Output, ) -> (bool, Self::State); // Equality on states. If you are using a simple data type for states, // you can use the `ShallowEqual` function implemented below. fn equal(&self, state1: &Self::State, state2: &Self::State) -> bool { state1 == state2 } } ================================================ FILE: courses/dss/linearizability/src/models.rs ================================================ use std::collections::HashMap; use super::model::{EventKind, Events, Model, Operations}; #[derive(Clone, Debug)] pub enum Op { Get, Put, Append, } #[derive(Clone, Debug)] pub struct KvInput { pub op: Op, pub key: String, pub value: String, } #[derive(Clone, Debug)] pub struct KvOutput { pub value: String, } #[derive(Clone, Default)] pub struct KvModel {} impl Model for KvModel { type State = String; type Input = KvInput; type Output = KvOutput; fn partition( &self, history: Operations, ) -> Vec> { let mut map = HashMap::new(); for op in history { let v = map.entry(op.input.key.clone()).or_insert_with(Vec::new); (*v).push(op); } let mut ret = vec![]; for (_, ops) in map { ret.push(ops); } ret } fn partition_event( &self, history: Events, ) -> Vec> { let mut m = HashMap::new(); let mut matched: HashMap = HashMap::new(); for event in history { match event.kind { EventKind::CallEvent => { let key = event.value.input().key.clone(); matched.insert(event.id, key.clone()); m.entry(key).or_insert_with(Vec::new).push(event); } EventKind::ReturnEvent => { let key = matched[&event.id].clone(); m.entry(key).or_insert_with(Vec::new).push(event); } } } let mut ret = vec![]; for (_, v) in m { ret.push(v); } ret } fn init(&self) -> Self::State { // note: we are modeling a single key's value here; // we're partitioning by key, so this is okay "".to_string() } fn step( &self, state: &Self::State, input: &Self::Input, output: &Self::Output, ) -> (bool, Self::State) { match input.op { Op::Get => (&output.value == state, state.clone()), Op::Put => (true, input.value.clone()), Op::Append => (true, state.clone() + &input.value), } } } #[cfg(test)] mod tests { use std::collections::HashMap; use std::fs::File; use std::io::{BufRead, BufReader, Result}; use super::super::check_events; use super::{KvInput, KvModel, KvOutput, Op}; use crate::model::{Event, EventKind, Events, Model, Value}; use regex::Regex; fn check_kv(log_name: String, correct: bool) { let model = KvModel {}; let file_name = format!("../linearizability/test_data/{}.txt", &log_name); let events = match parse_kv_log(&file_name) { Ok(events) => events, Err(e) => panic!("parse kv log {} failed: {}", &file_name, e), }; assert_eq!(check_events(model, events), correct); } fn parse_kv_log( file_name: &str, ) -> Result::Input, ::Output>> { lazy_static::lazy_static! { static ref INVOKE_GET: Regex = Regex::new( r#"\{:process (\d+), :type :invoke, :f :get, :key "(.*)", :value nil\}"# ) .unwrap(); static ref INVOKE_PUT: Regex = Regex::new( r#"\{:process (\d+), :type :invoke, :f :put, :key "(.*)", :value "(.*)"\}"# ) .unwrap(); static ref INVOKE_APPEND: Regex = Regex::new( r#"\{:process (\d+), :type :invoke, :f :append, :key "(.*)", :value "(.*)"\}"# ) .unwrap(); static ref RETURN_GET: Regex = Regex::new(r#"\{:process (\d+), :type :ok, :f :get, :key ".*", :value "(.*)"\}"#) .unwrap(); static ref RETURN_PUT: Regex = Regex::new(r#"\{:process (\d+), :type :ok, :f :put, :key ".*", :value ".*"\}"#) .unwrap(); static ref RETURN_APPEND: Regex = Regex::new(r#"\{:process (\d+), :type :ok, :f :append, :key ".*", :value ".*"\}"#) .unwrap(); } let f = File::open(file_name)?; let buf_reader = BufReader::new(f); let mut events = vec![]; let mut id = 0; let mut procid_map: HashMap = HashMap::new(); for line in buf_reader.lines() { let contents = line.unwrap(); if let Some(args) = INVOKE_GET.captures(&contents) { events.push(Event { kind: EventKind::CallEvent, value: Value::Input(KvInput { op: Op::Get, key: args[2].to_string(), value: "".to_string(), }), id, }); procid_map.insert(args[1].to_string().parse().unwrap(), id); id += 1; } else if let Some(args) = INVOKE_PUT.captures(&contents) { events.push(Event { kind: EventKind::CallEvent, value: Value::Input(KvInput { op: Op::Put, key: args[2].to_string(), value: args[3].to_string(), }), id, }); procid_map.insert(args[1].to_string().parse().unwrap(), id); id += 1; } else if let Some(args) = INVOKE_APPEND.captures(&contents) { events.push(Event { kind: EventKind::CallEvent, value: Value::Input(KvInput { op: Op::Append, key: args[2].to_string(), value: args[3].to_string(), }), id, }); procid_map.insert(args[1].to_string().parse().unwrap(), id); id += 1; } else if let Some(args) = RETURN_GET.captures(&contents) { let match_id = procid_map .remove(&args[1].to_string().parse().unwrap()) .unwrap(); events.push(Event { kind: EventKind::ReturnEvent, value: Value::Output(KvOutput { value: args[2].to_string(), }), id: match_id, }); } else if let Some(args) = RETURN_PUT.captures(&contents) { let match_id = procid_map .remove(&args[1].to_string().parse().unwrap()) .unwrap(); events.push(Event { kind: EventKind::ReturnEvent, value: Value::Output(KvOutput { value: "".to_string(), }), id: match_id, }); } else if let Some(args) = RETURN_APPEND.captures(&contents) { let match_id = procid_map .remove(&args[1].to_string().parse().unwrap()) .unwrap(); events.push(Event { kind: EventKind::ReturnEvent, value: Value::Output(KvOutput { value: "".to_string(), }), id: match_id, }); } else { unreachable!(); } } for (_, match_id) in procid_map { events.push(Event { kind: EventKind::ReturnEvent, value: Value::Output(KvOutput { value: "".to_string(), }), id: match_id, }) } Ok(events) } #[test] fn test_kv_1client_ok() { check_kv("c01-ok".to_string(), true) } #[test] fn test_kv_1client_bad() { check_kv("c01-bad".to_string(), false) } #[test] fn test_kv_10client_ok() { check_kv("c10-ok".to_string(), true) } #[test] fn test_kv_10client_bad() { check_kv("c10-bad".to_string(), false) } #[test] fn test_kv_50client_ok() { check_kv("c50-ok".to_string(), true) } #[test] fn test_kv_50client_bad() { check_kv("c50-bad".to_string(), false) } } ================================================ FILE: courses/dss/linearizability/test_data/c01-bad.txt ================================================ {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 0 y"} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 0 y"} {:process 0, :type :invoke, :f :get, :key "7", :value nil} {:process 0, :type :ok, :f :get, :key "7", :value ""} {:process 0, :type :invoke, :f :get, :key "6", :value nil} {:process 0, :type :ok, :f :get, :key "6", :value ""} {:process 0, :type :invoke, :f :get, :key "5", :value nil} {:process 0, :type :ok, :f :get, :key "5", :value ""} {:process 0, :type :invoke, :f :get, :key "2", :value nil} {:process 0, :type :ok, :f :get, :key "2", :value ""} {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 1 y"} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 1 y"} {:process 0, :type :invoke, :f :get, :key "2", :value nil} {:process 0, :type :ok, :f :get, :key "2", :value ""} {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 2 y"} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 2 y"} {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 3 y"} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 3 y"} {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 4 y"} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 4 y"} {:process 0, :type :invoke, :f :append, :key "5", :value "x 0 5 y"} {:process 0, :type :ok, :f :append, :key "5", :value "x 0 5 y"} {:process 0, :type :invoke, :f :get, :key "6", :value nil} {:process 0, :type :ok, :f :get, :key "6", :value ""} {:process 0, :type :invoke, :f :append, :key "1", :value "x 0 6 y"} {:process 0, :type :ok, :f :append, :key "1", :value "x 0 6 y"} {:process 0, :type :invoke, :f :get, :key "1", :value nil} {:process 0, :type :ok, :f :get, :key "1", :value "x 0 6 y"} {:process 0, :type :invoke, :f :get, :key "3", :value nil} {:process 0, :type :ok, :f :get, :key "3", :value ""} {:process 0, :type :invoke, :f :append, :key "2", :value "x 0 7 y"} {:process 0, :type :ok, :f :append, :key "2", :value "x 0 7 y"} {:process 0, :type :invoke, :f :get, :key "0", :value nil} {:process 0, :type :ok, :f :get, :key "0", :value "x 0 0 yx 0 1 yx 0 2 yx 0 3 yx 0 4 y"} {:process 0, :type :invoke, :f :append, :key "1", :value "x 0 8 y"} {:process 0, :type :ok, :f :append, :key "1", :value "x 0 8 y"} {:process 0, :type :invoke, :f :append, :key "7", :value "x 0 0 y"} {:process 0, :type :ok, :f :append, :key "7", :value "x 0 0 y"} {:process 0, :type :invoke, :f :get, :key "0", :value nil} {:process 0, :type :ok, :f :get, :key "0", :value "x 0 0 yx 0 1 yx 0 2 yx 0 3 yx 0 4 y"} {:process 0, :type :invoke, :f :get, :key "2", :value nil} {:process 0, :type :ok, :f :get, :key "2", :value "x 0 7 y"} {:process 0, :type :invoke, :f :get, :key "5", :value nil} {:process 0, :type :ok, :f :get, :key "5", :value "x 0 5 y"} {:process 0, :type :invoke, :f :get, :key "2", :value nil} {:process 0, :type :ok, :f :get, :key "2", :value "x 0 7 y"} {:process 0, :type :invoke, :f :append, :key "6", :value "x 0 1 y"} {:process 0, :type :ok, :f :append, :key "6", :value "x 0 1 y"} {:process 0, :type :invoke, :f :get, :key "5", :value nil} {:process 0, :type :ok, :f :get, :key "5", :value "x 0 5 y"} {:process 0, :type :invoke, :f :put, :key "1", :value "x 0 2 y"} {:process 0, :type :ok, :f :put, :key "1", :value "x 0 2 y"} {:process 0, :type :invoke, :f :get, :key "6", :value nil} {:process 0, :type :ok, :f :get, :key "6", :value "x 0 1 y"} {:process 0, :type :invoke, :f :append, :key "7", :value "x 0 3 y"} {:process 0, :type :ok, :f :append, :key "7", :value "x 0 3 y"} {:process 0, :type :invoke, :f :append, :key "3", :value "x 0 4 y"} {:process 0, :type :ok, :f :append, :key "3", :value "x 0 4 y"} {:process 0, :type :invoke, :f :get, :key "7", :value nil} {:process 0, :type :ok, :f :get, :key "7", :value "x 0 0 y"} {:process 0, :type :invoke, :f :append, :key "3", :value "x 0 5 y"} {:process 0, :type :ok, :f :append, :key "3", :value "x 0 5 y"} {:process 0, :type :invoke, :f :append, :key "6", :value "x 0 6 y"} {:process 0, :type :ok, :f :append, :key "6", :value "x 0 6 y"} {:process 0, :type :invoke, :f :append, :key "4", :value "x 0 7 y"} {:process 0, :type :ok, :f :append, :key "4", :value "x 0 7 y"} {:process 0, :type :invoke, :f :append, :key "6", :value "x 0 8 y"} {:process 0, :type :ok, :f :append, :key "6", :value "x 0 8 y"} {:process 0, :type :invoke, :f :append, :key "3", :value "x 0 9 y"} {:process 0, :type :ok, :f :append, :key "3", :value "x 0 9 y"} {:process 0, :type :invoke, :f :get, :key "2", :value nil} {:process 0, :type :ok, :f :get, :key "2", :value "x 0 7 y"} {:process 0, :type :invoke, :f :get, :key "7", :value nil} {:process 0, :type :ok, :f :get, :key "7", :value "x 0 0 yx 0 3 y"} {:process 0, :type :invoke, :f :put, :key "2", :value "x 0 10 y"} {:process 0, :type :ok, :f :put, :key "2", :value "x 0 10 y"} ================================================ FILE: courses/dss/linearizability/test_data/c01-ok.txt ================================================ {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 0 y"} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 0 y"} {:process 0, :type :invoke, :f :append, :key "4", :value "x 0 1 y"} {:process 0, :type :ok, :f :append, :key "4", :value "x 0 1 y"} {:process 0, :type :invoke, :f :append, :key "9", :value "x 0 2 y"} {:process 0, :type :ok, :f :append, :key "9", :value "x 0 2 y"} {:process 0, :type :invoke, :f :append, :key "4", :value "x 0 3 y"} {:process 0, :type :ok, :f :append, :key "4", :value "x 0 3 y"} {:process 0, :type :invoke, :f :get, :key "5", :value nil} {:process 0, :type :ok, :f :get, :key "5", :value ""} {:process 0, :type :invoke, :f :get, :key "0", :value nil} {:process 0, :type :ok, :f :get, :key "0", :value "x 0 0 y"} {:process 0, :type :invoke, :f :append, :key "7", :value "x 0 4 y"} {:process 0, :type :ok, :f :append, :key "7", :value "x 0 4 y"} {:process 0, :type :invoke, :f :get, :key "7", :value nil} {:process 0, :type :ok, :f :get, :key "7", :value "x 0 4 y"} {:process 0, :type :invoke, :f :append, :key "9", :value "x 0 5 y"} {:process 0, :type :ok, :f :append, :key "9", :value "x 0 5 y"} {:process 0, :type :invoke, :f :get, :key "9", :value nil} {:process 0, :type :ok, :f :get, :key "9", :value "x 0 2 yx 0 5 y"} {:process 0, :type :invoke, :f :append, :key "2", :value "x 0 6 y"} {:process 0, :type :ok, :f :append, :key "2", :value "x 0 6 y"} {:process 0, :type :invoke, :f :append, :key "2", :value "x 0 7 y"} {:process 0, :type :ok, :f :append, :key "2", :value "x 0 7 y"} {:process 0, :type :invoke, :f :get, :key "1", :value nil} {:process 0, :type :ok, :f :get, :key "1", :value ""} {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 8 y"} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 8 y"} {:process 0, :type :invoke, :f :put, :key "9", :value "x 0 9 y"} {:process 0, :type :ok, :f :put, :key "9", :value "x 0 9 y"} {:process 0, :type :invoke, :f :get, :key "8", :value nil} {:process 0, :type :ok, :f :get, :key "8", :value ""} {:process 0, :type :invoke, :f :get, :key "8", :value nil} {:process 0, :type :ok, :f :get, :key "8", :value ""} {:process 0, :type :invoke, :f :get, :key "9", :value nil} {:process 0, :type :ok, :f :get, :key "9", :value "x 0 9 y"} {:process 0, :type :invoke, :f :append, :key "1", :value "x 0 10 y"} {:process 0, :type :ok, :f :append, :key "1", :value "x 0 10 y"} {:process 0, :type :invoke, :f :append, :key "2", :value "x 0 11 y"} {:process 0, :type :ok, :f :append, :key "2", :value "x 0 11 y"} {:process 0, :type :invoke, :f :get, :key "7", :value nil} {:process 0, :type :ok, :f :get, :key "7", :value "x 0 4 y"} {:process 0, :type :invoke, :f :get, :key "7", :value nil} {:process 0, :type :ok, :f :get, :key "7", :value "x 0 4 y"} {:process 0, :type :invoke, :f :append, :key "5", :value "x 0 12 y"} {:process 0, :type :ok, :f :append, :key "5", :value "x 0 12 y"} {:process 0, :type :invoke, :f :get, :key "6", :value nil} {:process 0, :type :ok, :f :get, :key "6", :value ""} {:process 0, :type :invoke, :f :get, :key "5", :value nil} {:process 0, :type :ok, :f :get, :key "5", :value "x 0 12 y"} {:process 0, :type :invoke, :f :append, :key "7", :value "x 0 0 y"} {:process 0, :type :ok, :f :append, :key "7", :value "x 0 0 y"} {:process 0, :type :invoke, :f :get, :key "5", :value nil} {:process 0, :type :ok, :f :get, :key "5", :value "x 0 12 y"} {:process 0, :type :invoke, :f :append, :key "7", :value "x 0 1 y"} {:process 0, :type :ok, :f :append, :key "7", :value "x 0 1 y"} {:process 0, :type :invoke, :f :append, :key "2", :value "x 0 2 y"} {:process 0, :type :ok, :f :append, :key "2", :value "x 0 2 y"} {:process 0, :type :invoke, :f :get, :key "8", :value nil} {:process 0, :type :ok, :f :get, :key "8", :value ""} {:process 0, :type :invoke, :f :get, :key "9", :value nil} {:process 0, :type :ok, :f :get, :key "9", :value "x 0 9 y"} {:process 0, :type :invoke, :f :append, :key "8", :value "x 0 3 y"} {:process 0, :type :ok, :f :append, :key "8", :value "x 0 3 y"} {:process 0, :type :invoke, :f :append, :key "5", :value "x 0 4 y"} {:process 0, :type :ok, :f :append, :key "5", :value "x 0 4 y"} {:process 0, :type :invoke, :f :get, :key "5", :value nil} {:process 0, :type :ok, :f :get, :key "5", :value "x 0 12 yx 0 4 y"} {:process 0, :type :invoke, :f :get, :key "5", :value nil} {:process 0, :type :ok, :f :get, :key "5", :value "x 0 12 yx 0 4 y"} {:process 0, :type :invoke, :f :append, :key "1", :value "x 0 5 y"} {:process 0, :type :ok, :f :append, :key "1", :value "x 0 5 y"} {:process 0, :type :invoke, :f :append, :key "3", :value "x 0 6 y"} {:process 0, :type :ok, :f :append, :key "3", :value "x 0 6 y"} {:process 0, :type :invoke, :f :append, :key "7", :value "x 0 7 y"} {:process 0, :type :ok, :f :append, :key "7", :value "x 0 7 y"} {:process 0, :type :invoke, :f :get, :key "0", :value nil} {:process 0, :type :ok, :f :get, :key "0", :value "x 0 0 yx 0 8 y"} {:process 0, :type :invoke, :f :append, :key "2", :value "x 0 8 y"} {:process 0, :type :ok, :f :append, :key "2", :value "x 0 8 y"} {:process 0, :type :invoke, :f :append, :key "4", :value "x 0 9 y"} {:process 0, :type :ok, :f :append, :key "4", :value "x 0 9 y"} {:process 0, :type :invoke, :f :put, :key "4", :value "x 0 10 y"} {:process 0, :type :ok, :f :put, :key "4", :value "x 0 10 y"} {:process 0, :type :invoke, :f :get, :key "1", :value nil} {:process 0, :type :ok, :f :get, :key "1", :value "x 0 10 yx 0 5 y"} {:process 0, :type :invoke, :f :append, :key "7", :value "x 0 11 y"} {:process 0, :type :ok, :f :append, :key "7", :value "x 0 11 y"} {:process 0, :type :invoke, :f :append, :key "4", :value "x 0 12 y"} {:process 0, :type :ok, :f :append, :key "4", :value "x 0 12 y"} {:process 0, :type :invoke, :f :append, :key "7", :value "x 0 13 y"} {:process 0, :type :ok, :f :append, :key "7", :value "x 0 13 y"} {:process 0, :type :invoke, :f :append, :key "5", :value "x 0 14 y"} {:process 0, :type :ok, :f :append, :key "5", :value "x 0 14 y"} {:process 0, :type :invoke, :f :get, :key "8", :value nil} {:process 0, :type :ok, :f :get, :key "8", :value "x 0 3 y"} {:process 0, :type :invoke, :f :get, :key "3", :value nil} {:process 0, :type :ok, :f :get, :key "3", :value "x 0 6 y"} {:process 0, :type :invoke, :f :get, :key "3", :value nil} {:process 0, :type :ok, :f :get, :key "3", :value "x 0 6 y"} {:process 0, :type :invoke, :f :get, :key "7", :value nil} {:process 0, :type :ok, :f :get, :key "7", :value "x 0 4 yx 0 0 yx 0 1 yx 0 7 yx 0 11 yx 0 13 y"} {:process 0, :type :invoke, :f :append, :key "5", :value "x 0 15 y"} {:process 0, :type :ok, :f :append, :key "5", :value "x 0 15 y"} {:process 0, :type :invoke, :f :get, :key "3", :value nil} {:process 0, :type :ok, :f :get, :key "3", :value "x 0 6 y"} {:process 0, :type :invoke, :f :get, :key "2", :value nil} {:process 0, :type :ok, :f :get, :key "2", :value "x 0 6 yx 0 7 yx 0 11 yx 0 2 yx 0 8 y"} {:process 0, :type :invoke, :f :append, :key "2", :value "x 0 16 y"} {:process 0, :type :ok, :f :append, :key "2", :value "x 0 16 y"} {:process 0, :type :invoke, :f :append, :key "5", :value "x 0 17 y"} {:process 0, :type :ok, :f :append, :key "5", :value "x 0 17 y"} {:process 0, :type :invoke, :f :append, :key "6", :value "x 0 18 y"} {:process 0, :type :ok, :f :append, :key "6", :value "x 0 18 y"} {:process 0, :type :invoke, :f :append, :key "3", :value "x 0 19 y"} {:process 0, :type :ok, :f :append, :key "3", :value "x 0 19 y"} ================================================ FILE: courses/dss/linearizability/test_data/c10-bad.txt ================================================ {:process 9, :type :invoke, :f :append, :key "0", :value "x 9 0 y"} {:process 4, :type :invoke, :f :append, :key "1", :value "x 4 0 y"} {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 0 y"} {:process 1, :type :invoke, :f :get, :key "9", :value nil} {:process 2, :type :invoke, :f :append, :key "9", :value "x 2 0 y"} {:process 6, :type :invoke, :f :append, :key "9", :value "x 6 0 y"} {:process 3, :type :invoke, :f :append, :key "1", :value "x 3 0 y"} {:process 5, :type :invoke, :f :get, :key "1", :value nil} {:process 7, :type :invoke, :f :get, :key "9", :value nil} {:process 8, :type :invoke, :f :get, :key "6", :value nil} {:process 5, :type :ok, :f :get, :key "1", :value ""} {:process 5, :type :invoke, :f :put, :key "8", :value "x 5 0 y"} {:process 1, :type :ok, :f :get, :key "9", :value ""} {:process 1, :type :invoke, :f :put, :key "8", :value "x 1 0 y"} {:process 7, :type :ok, :f :get, :key "9", :value ""} {:process 7, :type :invoke, :f :append, :key "4", :value "x 7 0 y"} {:process 8, :type :ok, :f :get, :key "6", :value ""} {:process 8, :type :invoke, :f :append, :key "0", :value "x 8 0 y"} {:process 3, :type :ok, :f :append, :key "1", :value "x 3 0 y"} {:process 3, :type :invoke, :f :get, :key "4", :value nil} {:process 3, :type :ok, :f :get, :key "4", :value ""} {:process 3, :type :invoke, :f :append, :key "1", :value "x 3 1 y"} {:process 9, :type :ok, :f :append, :key "0", :value "x 9 0 y"} {:process 9, :type :invoke, :f :append, :key "3", :value "x 9 1 y"} {:process 3, :type :ok, :f :append, :key "1", :value "x 3 1 y"} {:process 3, :type :invoke, :f :get, :key "6", :value nil} {:process 9, :type :ok, :f :append, :key "3", :value "x 9 1 y"} {:process 9, :type :invoke, :f :get, :key "9", :value nil} {:process 3, :type :ok, :f :get, :key "6", :value ""} {:process 3, :type :invoke, :f :put, :key "8", :value "x 3 2 y"} {:process 3, :type :ok, :f :put, :key "8", :value "x 3 2 y"} {:process 3, :type :invoke, :f :append, :key "5", :value "x 3 3 y"} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 0 y"} {:process 0, :type :invoke, :f :put, :key "2", :value "x 0 1 y"} {:process 0, :type :ok, :f :put, :key "2", :value "x 0 1 y"} {:process 0, :type :invoke, :f :append, :key "6", :value "x 0 2 y"} {:process 9, :type :ok, :f :get, :key "9", :value ""} {:process 9, :type :invoke, :f :append, :key "7", :value "x 9 2 y"} {:process 8, :type :ok, :f :append, :key "0", :value "x 8 0 y"} {:process 8, :type :invoke, :f :append, :key "2", :value "x 8 1 y"} {:process 6, :type :ok, :f :append, :key "9", :value "x 6 0 y"} {:process 6, :type :invoke, :f :get, :key "1", :value nil} {:process 5, :type :ok, :f :put, :key "8", :value "x 5 0 y"} {:process 5, :type :invoke, :f :append, :key "8", :value "x 5 1 y"} {:process 1, :type :ok, :f :put, :key "8", :value "x 1 0 y"} {:process 1, :type :invoke, :f :get, :key "2", :value nil} {:process 1, :type :ok, :f :get, :key "2", :value "x 0 1 y"} {:process 1, :type :invoke, :f :get, :key "1", :value nil} {:process 5, :type :ok, :f :append, :key "8", :value "x 5 1 y"} {:process 5, :type :invoke, :f :get, :key "2", :value nil} {:process 1, :type :ok, :f :get, :key "1", :value "x 3 0 yx 3 1 yx 4 0 y"} {:process 1, :type :invoke, :f :get, :key "3", :value nil} {:process 5, :type :ok, :f :get, :key "2", :value "x 0 1 y"} {:process 5, :type :invoke, :f :append, :key "7", :value "x 5 2 y"} {:process 1, :type :ok, :f :get, :key "3", :value "x 9 1 y"} {:process 1, :type :invoke, :f :append, :key "2", :value "x 1 1 y"} {:process 6, :type :ok, :f :get, :key "1", :value "x 3 0 yx 3 1 y"} {:process 6, :type :invoke, :f :append, :key "5", :value "x 6 1 y"} {:process 2, :type :ok, :f :append, :key "9", :value "x 2 0 y"} {:process 2, :type :invoke, :f :get, :key "8", :value nil} {:process 2, :type :ok, :f :get, :key "8", :value "x 1 0 yx 5 1 y"} {:process 2, :type :invoke, :f :get, :key "2", :value nil} {:process 9, :type :ok, :f :append, :key "7", :value "x 9 2 y"} {:process 9, :type :invoke, :f :get, :key "8", :value nil} {:process 9, :type :ok, :f :get, :key "8", :value "x 1 0 yx 5 1 y"} {:process 9, :type :invoke, :f :get, :key "7", :value nil} {:process 9, :type :ok, :f :get, :key "7", :value "x 5 2 yx 9 2 y"} {:process 9, :type :invoke, :f :append, :key "2", :value "x 9 3 y"} {:process 9, :type :ok, :f :append, :key "2", :value "x 9 3 y"} {:process 9, :type :invoke, :f :append, :key "2", :value "x 9 4 y"} {:process 9, :type :ok, :f :append, :key "2", :value "x 9 4 y"} {:process 9, :type :invoke, :f :append, :key "2", :value "x 9 5 y"} {:process 9, :type :ok, :f :append, :key "2", :value "x 9 5 y"} {:process 9, :type :invoke, :f :get, :key "4", :value nil} {:process 0, :type :ok, :f :append, :key "6", :value "x 0 2 y"} {:process 8, :type :ok, :f :append, :key "2", :value "x 8 1 y"} {:process 8, :type :invoke, :f :get, :key "3", :value nil} {:process 0, :type :invoke, :f :get, :key "5", :value nil} {:process 0, :type :ok, :f :get, :key "5", :value "x 3 3 y"} {:process 0, :type :invoke, :f :get, :key "5", :value nil} {:process 7, :type :ok, :f :append, :key "4", :value "x 7 0 y"} {:process 7, :type :invoke, :f :append, :key "0", :value "x 7 1 y"} {:process 0, :type :ok, :f :get, :key "5", :value "x 3 3 y"} {:process 0, :type :invoke, :f :append, :key "2", :value "x 0 3 y"} {:process 9, :type :ok, :f :get, :key "4", :value "x 7 0 y"} {:process 9, :type :invoke, :f :get, :key "5", :value nil} {:process 2, :type :ok, :f :get, :key "2", :value "x 0 1 yx 9 3 yx 9 4 yx 9 5 yx 8 1 y"} {:process 2, :type :invoke, :f :get, :key "2", :value nil} {:process 9, :type :ok, :f :get, :key "5", :value "x 3 3 y"} {:process 9, :type :invoke, :f :get, :key "1", :value nil} {:process 9, :type :ok, :f :get, :key "1", :value "x 3 0 yx 3 1 y"} {:process 9, :type :invoke, :f :append, :key "3", :value "x 9 6 y"} {:process 7, :type :ok, :f :append, :key "0", :value "x 7 1 y"} {:process 7, :type :invoke, :f :append, :key "5", :value "x 7 2 y"} {:process 2, :type :ok, :f :get, :key "2", :value "x 0 1 yx 9 3 yx 9 4 yx 9 5 yx 8 1 y"} {:process 2, :type :invoke, :f :get, :key "3", :value nil} {:process 0, :type :ok, :f :append, :key "2", :value "x 0 3 y"} {:process 0, :type :invoke, :f :append, :key "2", :value "x 0 4 y"} {:process 7, :type :ok, :f :append, :key "5", :value "x 7 2 y"} {:process 7, :type :invoke, :f :append, :key "6", :value "x 7 3 y"} {:process 0, :type :ok, :f :append, :key "2", :value "x 0 4 y"} {:process 0, :type :invoke, :f :get, :key "9", :value nil} {:process 8, :type :ok, :f :get, :key "3", :value "x 9 1 y"} {:process 8, :type :invoke, :f :append, :key "1", :value "x 8 2 y"} {:process 0, :type :ok, :f :get, :key "9", :value "x 6 0 yx 2 0 y"} {:process 0, :type :invoke, :f :append, :key "4", :value "x 0 5 y"} {:process 7, :type :ok, :f :append, :key "6", :value "x 7 3 y"} {:process 7, :type :invoke, :f :put, :key "4", :value "x 7 4 y"} {:process 2, :type :ok, :f :get, :key "3", :value "x 9 1 y"} {:process 2, :type :invoke, :f :get, :key "9", :value nil} {:process 2, :type :ok, :f :get, :key "9", :value ""} {:process 2, :type :invoke, :f :append, :key "6", :value "x 2 1 y"} {:process 0, :type :ok, :f :append, :key "4", :value "x 0 5 y"} {:process 0, :type :invoke, :f :get, :key "8", :value nil} {:process 0, :type :ok, :f :get, :key "8", :value "x 1 0 yx 5 1 y"} {:process 0, :type :invoke, :f :get, :key "5", :value nil} {:process 0, :type :ok, :f :get, :key "5", :value "x 3 3 yx 7 2 y"} {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 6 y"} {:process 9, :type :ok, :f :append, :key "3", :value "x 9 6 y"} {:process 9, :type :invoke, :f :get, :key "0", :value nil} {:process 9, :type :ok, :f :get, :key "0", :value "x 9 0 yx 0 0 yx 8 0 yx 7 1 y"} {:process 9, :type :invoke, :f :append, :key "7", :value "x 9 7 y"} {:process 8, :type :ok, :f :append, :key "1", :value "x 8 2 y"} {:process 8, :type :invoke, :f :append, :key "5", :value "x 8 3 y"} {:process 9, :type :ok, :f :append, :key "7", :value "x 9 7 y"} {:process 9, :type :invoke, :f :append, :key "2", :value "x 9 8 y"} {:process 8, :type :ok, :f :append, :key "5", :value "x 8 3 y"} {:process 8, :type :invoke, :f :append, :key "2", :value "x 8 4 y"} {:process 9, :type :ok, :f :append, :key "2", :value "x 9 8 y"} {:process 8, :type :ok, :f :append, :key "2", :value "x 8 4 y"} {:process 9, :type :invoke, :f :get, :key "9", :value nil} {:process 8, :type :invoke, :f :get, :key "6", :value nil} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 6 y"} {:process 0, :type :invoke, :f :get, :key "8", :value nil} {:process 7, :type :ok, :f :put, :key "4", :value "x 7 4 y"} {:process 7, :type :invoke, :f :append, :key "8", :value "x 7 5 y"} {:process 0, :type :ok, :f :get, :key "8", :value "x 1 0 yx 5 1 y"} {:process 0, :type :invoke, :f :append, :key "7", :value "x 0 7 y"} {:process 7, :type :ok, :f :append, :key "8", :value "x 7 5 y"} {:process 7, :type :invoke, :f :append, :key "0", :value "x 7 6 y"} {:process 7, :type :ok, :f :append, :key "0", :value "x 7 6 y"} {:process 0, :type :ok, :f :append, :key "7", :value "x 0 7 y"} {:process 7, :type :invoke, :f :get, :key "0", :value nil} {:process 0, :type :invoke, :f :append, :key "6", :value "x 0 8 y"} {:process 7, :type :ok, :f :get, :key "0", :value "x 9 0 yx 0 0 yx 8 0 yx 7 1 yx 0 6 yx 7 6 y"} {:process 7, :type :invoke, :f :append, :key "0", :value "x 7 7 y"} {:process 0, :type :ok, :f :append, :key "6", :value "x 0 8 y"} {:process 0, :type :invoke, :f :get, :key "4", :value nil} {:process 9, :type :ok, :f :get, :key "9", :value ""} {:process 9, :type :invoke, :f :append, :key "1", :value "x 9 9 y"} {:process 8, :type :ok, :f :get, :key "6", :value "x 0 2 y"} {:process 8, :type :invoke, :f :get, :key "3", :value nil} {:process 8, :type :ok, :f :get, :key "3", :value "x 9 1 y"} {:process 8, :type :invoke, :f :get, :key "7", :value nil} {:process 0, :type :ok, :f :get, :key "4", :value "x 7 4 y"} {:process 0, :type :invoke, :f :get, :key "2", :value nil} {:process 8, :type :ok, :f :get, :key "7", :value ""} {:process 8, :type :invoke, :f :get, :key "0", :value nil} {:process 8, :type :ok, :f :get, :key "0", :value "x 9 0 yx 0 0 yx 8 0 y"} {:process 8, :type :invoke, :f :get, :key "7", :value nil} {:process 8, :type :ok, :f :get, :key "7", :value ""} {:process 8, :type :invoke, :f :append, :key "3", :value "x 8 5 y"} {:process 0, :type :ok, :f :get, :key "2", :value "x 0 1 yx 9 3 yx 9 4 yx 9 5 yx 8 1 yx 0 3 yx 0 4 yx 9 8 yx 8 4 y"} {:process 0, :type :invoke, :f :get, :key "9", :value nil} {:process 0, :type :ok, :f :get, :key "9", :value "x 6 0 yx 2 0 y"} {:process 0, :type :invoke, :f :append, :key "9", :value "x 0 9 y"} {:process 7, :type :ok, :f :append, :key "0", :value "x 7 7 y"} {:process 7, :type :invoke, :f :append, :key "2", :value "x 7 8 y"} {:process 0, :type :ok, :f :append, :key "9", :value "x 0 9 y"} {:process 0, :type :invoke, :f :get, :key "0", :value nil} {:process 0, :type :ok, :f :get, :key "0", :value "x 9 0 yx 0 0 yx 8 0 yx 7 1 yx 0 6 yx 7 6 yx 7 7 y"} {:process 0, :type :invoke, :f :get, :key "7", :value nil} {:process 0, :type :ok, :f :get, :key "7", :value "x 5 2 yx 9 2 yx 9 7 yx 0 7 y"} {:process 0, :type :invoke, :f :get, :key "7", :value nil} {:process 0, :type :ok, :f :get, :key "7", :value "x 5 2 yx 9 2 yx 9 7 yx 0 7 y"} {:process 0, :type :invoke, :f :get, :key "2", :value nil} {:process 0, :type :ok, :f :get, :key "2", :value "x 0 1 yx 9 3 yx 9 4 yx 9 5 yx 8 1 yx 0 3 yx 0 4 yx 9 8 yx 8 4 y"} {:process 0, :type :invoke, :f :get, :key "1", :value nil} {:process 0, :type :ok, :f :get, :key "1", :value "x 3 0 yx 3 1 yx 4 0 yx 8 2 y"} {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 10 y"} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 10 y"} {:process 0, :type :invoke, :f :append, :key "3", :value "x 0 11 y"} {:process 6, :type :ok, :f :append, :key "5", :value "x 6 1 y"} {:process 6, :type :invoke, :f :get, :key "3", :value nil} {:process 6, :type :ok, :f :get, :key "3", :value "x 9 1 yx 9 6 y"} {:process 6, :type :invoke, :f :append, :key "3", :value "x 6 2 y"} {:process 0, :type :ok, :f :append, :key "3", :value "x 0 11 y"} {:process 0, :type :invoke, :f :append, :key "4", :value "x 0 12 y"} {:process 7, :type :ok, :f :append, :key "2", :value "x 7 8 y"} {:process 7, :type :invoke, :f :append, :key "6", :value "x 7 9 y"} {:process 6, :type :ok, :f :append, :key "3", :value "x 6 2 y"} {:process 6, :type :invoke, :f :get, :key "2", :value nil} {:process 7, :type :ok, :f :append, :key "6", :value "x 7 9 y"} {:process 7, :type :invoke, :f :get, :key "9", :value nil} {:process 0, :type :ok, :f :append, :key "4", :value "x 0 12 y"} {:process 0, :type :invoke, :f :get, :key "6", :value nil} {:process 1, :type :ok, :f :append, :key "2", :value "x 1 1 y"} {:process 1, :type :invoke, :f :put, :key "1", :value "x 1 2 y"} {:process 0, :type :ok, :f :get, :key "6", :value "x 0 2 yx 7 3 yx 0 8 yx 7 9 y"} {:process 0, :type :invoke, :f :get, :key "5", :value nil} {:process 0, :type :ok, :f :get, :key "5", :value "x 3 3 yx 7 2 yx 8 3 yx 6 1 y"} {:process 0, :type :invoke, :f :append, :key "9", :value "x 0 13 y"} {:process 1, :type :ok, :f :put, :key "1", :value "x 1 2 y"} {:process 1, :type :invoke, :f :get, :key "4", :value nil} {:process 1, :type :ok, :f :get, :key "4", :value "x 7 4 yx 0 12 y"} {:process 1, :type :invoke, :f :get, :key "3", :value nil} {:process 0, :type :ok, :f :append, :key "9", :value "x 0 13 y"} {:process 0, :type :invoke, :f :append, :key "9", :value "x 0 14 y"} {:process 1, :type :ok, :f :get, :key "3", :value "x 9 1 yx 9 6 yx 0 11 yx 6 2 y"} {:process 1, :type :invoke, :f :append, :key "5", :value "x 1 3 y"} {:process 6, :type :ok, :f :get, :key "2", :value "x 0 1 yx 9 3 yx 9 4 yx 9 5 yx 8 1 yx 0 3 yx 0 4 yx 9 8 yx 8 4 yx 7 8 yx 1 1 y"} {:process 6, :type :invoke, :f :get, :key "4", :value nil} {:process 6, :type :ok, :f :get, :key "4", :value "x 7 4 yx 0 12 y"} {:process 6, :type :invoke, :f :get, :key "9", :value nil} {:process 7, :type :ok, :f :get, :key "9", :value "x 6 0 yx 2 0 yx 0 9 yx 0 13 y"} {:process 7, :type :invoke, :f :get, :key "5", :value nil} {:process 7, :type :ok, :f :get, :key "5", :value "x 3 3 yx 7 2 yx 8 3 yx 6 1 y"} {:process 7, :type :invoke, :f :append, :key "5", :value "x 7 10 y"} {:process 6, :type :ok, :f :get, :key "9", :value ""} {:process 6, :type :invoke, :f :append, :key "0", :value "x 6 3 y"} {:process 9, :type :ok, :f :append, :key "1", :value "x 9 9 y"} {:process 9, :type :invoke, :f :put, :key "6", :value "x 9 10 y"} {:process 8, :type :ok, :f :append, :key "3", :value "x 8 5 y"} {:process 8, :type :invoke, :f :get, :key "6", :value nil} {:process 8, :type :ok, :f :get, :key "6", :value "x 9 10 y"} {:process 8, :type :invoke, :f :append, :key "6", :value "x 8 6 y"} {:process 8, :type :ok, :f :append, :key "6", :value "x 8 6 y"} {:process 8, :type :invoke, :f :get, :key "0", :value nil} {:process 8, :type :ok, :f :get, :key "0", :value "x 9 0 yx 0 0 yx 8 0 yx 7 1 yx 0 6 yx 7 6 yx 7 7 yx 0 10 y"} {:process 8, :type :invoke, :f :append, :key "1", :value "x 8 7 y"} {:process 8, :type :ok, :f :append, :key "1", :value "x 8 7 y"} {:process 8, :type :invoke, :f :append, :key "3", :value "x 8 8 y"} {:process 8, :type :ok, :f :append, :key "3", :value "x 8 8 y"} {:process 8, :type :invoke, :f :get, :key "6", :value nil} {:process 8, :type :ok, :f :get, :key "6", :value "x 9 10 yx 8 6 y"} {:process 8, :type :invoke, :f :append, :key "6", :value "x 8 9 y"} {:process 8, :type :ok, :f :append, :key "6", :value "x 8 9 y"} {:process 8, :type :invoke, :f :append, :key "5", :value "x 8 10 y"} {:process 7, :type :ok, :f :append, :key "5", :value "x 7 10 y"} {:process 7, :type :invoke, :f :get, :key "1", :value nil} {:process 7, :type :ok, :f :get, :key "1", :value "x 1 2 yx 9 9 yx 8 7 y"} {:process 7, :type :invoke, :f :get, :key "5", :value nil} {:process 4, :type :ok, :f :append, :key "1", :value "x 4 0 y"} {:process 4, :type :invoke, :f :append, :key "1", :value "x 4 1 y"} {:process 0, :type :ok, :f :append, :key "9", :value "x 0 14 y"} {:process 0, :type :invoke, :f :get, :key "2", :value nil} {:process 7, :type :ok, :f :get, :key "5", :value "x 3 3 yx 7 2 yx 8 3 yx 6 1 yx 7 10 y"} {:process 7, :type :invoke, :f :get, :key "0", :value nil} {:process 4, :type :ok, :f :append, :key "1", :value "x 4 1 y"} {:process 4, :type :invoke, :f :append, :key "4", :value "x 4 2 y"} {:process 7, :type :ok, :f :get, :key "0", :value "x 9 0 yx 0 0 yx 8 0 yx 7 1 yx 0 6 yx 7 6 yx 7 7 yx 0 10 yx 6 3 y"} {:process 7, :type :invoke, :f :append, :key "0", :value "x 7 11 y"} {:process 0, :type :ok, :f :get, :key "2", :value "x 0 1 yx 9 3 yx 9 4 yx 9 5 yx 8 1 yx 0 3 yx 0 4 yx 9 8 yx 8 4 yx 7 8 yx 1 1 y"} {:process 0, :type :invoke, :f :append, :key "4", :value "x 0 15 y"} {:process 1, :type :ok, :f :append, :key "5", :value "x 1 3 y"} {:process 1, :type :invoke, :f :get, :key "4", :value nil} {:process 1, :type :ok, :f :get, :key "4", :value "x 7 4 yx 0 12 y"} {:process 1, :type :invoke, :f :put, :key "1", :value "x 1 4 y"} {:process 2, :type :ok, :f :append, :key "6", :value "x 2 1 y"} {:process 2, :type :invoke, :f :append, :key "2", :value "x 2 2 y"} {:process 0, :type :ok, :f :append, :key "4", :value "x 0 15 y"} {:process 0, :type :invoke, :f :append, :key "1", :value "x 0 16 y"} {:process 7, :type :ok, :f :append, :key "0", :value "x 7 11 y"} {:process 7, :type :invoke, :f :get, :key "4", :value nil} {:process 4, :type :ok, :f :append, :key "4", :value "x 4 2 y"} {:process 4, :type :invoke, :f :append, :key "8", :value "x 4 3 y"} {:process 1, :type :ok, :f :put, :key "1", :value "x 1 4 y"} {:process 1, :type :invoke, :f :append, :key "0", :value "x 1 5 y"} {:process 0, :type :ok, :f :append, :key "1", :value "x 0 16 y"} {:process 0, :type :invoke, :f :append, :key "1", :value "x 0 17 y"} {:process 7, :type :ok, :f :get, :key "4", :value "x 7 4 yx 0 12 yx 0 15 yx 4 2 y"} {:process 7, :type :invoke, :f :append, :key "4", :value "x 7 12 y"} {:process 4, :type :ok, :f :append, :key "8", :value "x 4 3 y"} {:process 4, :type :invoke, :f :get, :key "5", :value nil} {:process 4, :type :ok, :f :get, :key "5", :value "x 3 3 yx 7 2 yx 8 3 yx 6 1 yx 7 10 yx 1 3 y"} {:process 4, :type :invoke, :f :append, :key "2", :value "x 4 4 y"} {:process 9, :type :ok, :f :put, :key "6", :value "x 9 10 y"} {:process 9, :type :invoke, :f :get, :key "5", :value nil} {:process 9, :type :ok, :f :get, :key "5", :value "x 3 3 yx 7 2 yx 8 3 yx 6 1 yx 7 10 yx 1 3 y"} {:process 9, :type :invoke, :f :get, :key "7", :value nil} {:process 9, :type :ok, :f :get, :key "7", :value "x 5 2 yx 9 2 yx 9 7 yx 0 7 y"} {:process 9, :type :invoke, :f :get, :key "5", :value nil} {:process 8, :type :ok, :f :append, :key "5", :value "x 8 10 y"} {:process 8, :type :invoke, :f :append, :key "7", :value "x 8 11 y"} {:process 8, :type :ok, :f :append, :key "7", :value "x 8 11 y"} {:process 8, :type :invoke, :f :put, :key "4", :value "x 8 12 y"} {:process 8, :type :ok, :f :put, :key "4", :value "x 8 12 y"} {:process 8, :type :invoke, :f :put, :key "0", :value "x 8 13 y"} {:process 6, :type :ok, :f :append, :key "0", :value "x 6 3 y"} {:process 6, :type :invoke, :f :append, :key "3", :value "x 6 4 y"} {:process 6, :type :ok, :f :append, :key "3", :value "x 6 4 y"} {:process 6, :type :invoke, :f :append, :key "6", :value "x 6 5 y"} {:process 9, :type :ok, :f :get, :key "5", :value "x 3 3 yx 7 2 yx 8 3 yx 6 1 yx 7 10 yx 1 3 yx 8 10 y"} {:process 9, :type :invoke, :f :get, :key "0", :value nil} {:process 9, :type :ok, :f :get, :key "0", :value "x 9 0 yx 0 0 yx 8 0 yx 7 1 yx 0 6 yx 7 6 yx 7 7 yx 0 10 yx 6 3 yx 7 11 yx 1 5 y"} {:process 9, :type :invoke, :f :get, :key "8", :value nil} {:process 6, :type :ok, :f :append, :key "6", :value "x 6 5 y"} {:process 6, :type :invoke, :f :get, :key "9", :value nil} {:process 6, :type :ok, :f :get, :key "9", :value "x 6 0 yx 2 0 yx 0 9 yx 0 13 yx 0 14 y"} {:process 6, :type :invoke, :f :get, :key "1", :value nil} {:process 2, :type :ok, :f :append, :key "2", :value "x 2 2 y"} {:process 2, :type :invoke, :f :append, :key "9", :value "x 2 3 y"} {:process 9, :type :ok, :f :get, :key "8", :value "x 1 0 yx 5 1 yx 7 5 yx 4 3 y"} {:process 9, :type :invoke, :f :get, :key "5", :value nil} {:process 9, :type :ok, :f :get, :key "5", :value "x 3 3 yx 7 2 yx 8 3 yx 6 1 yx 7 10 yx 1 3 yx 8 10 y"} {:process 9, :type :invoke, :f :get, :key "2", :value nil} {:process 9, :type :ok, :f :get, :key "2", :value "x 0 1 yx 9 3 yx 9 4 yx 9 5 yx 8 1 yx 0 3 yx 0 4 yx 9 8 yx 8 4 yx 7 8 yx 1 1 y"} {:process 9, :type :invoke, :f :append, :key "8", :value "x 9 11 y"} {:process 6, :type :ok, :f :get, :key "1", :value "x 1 4 yx 0 16 yx 0 17 y"} {:process 6, :type :invoke, :f :get, :key "7", :value nil} {:process 6, :type :ok, :f :get, :key "7", :value "x 5 2 yx 9 2 yx 9 7 yx 0 7 yx 8 11 y"} {:process 6, :type :invoke, :f :get, :key "1", :value nil} {:process 6, :type :ok, :f :get, :key "1", :value "x 1 4 yx 0 16 yx 0 17 y"} {:process 6, :type :invoke, :f :put, :key "2", :value "x 6 6 y"} {:process 7, :type :ok, :f :append, :key "4", :value "x 7 12 y"} {:process 7, :type :invoke, :f :append, :key "4", :value "x 7 13 y"} {:process 7, :type :ok, :f :append, :key "4", :value "x 7 13 y"} {:process 7, :type :invoke, :f :get, :key "1", :value nil} {:process 1, :type :ok, :f :append, :key "0", :value "x 1 5 y"} {:process 1, :type :invoke, :f :append, :key "0", :value "x 1 6 y"} {:process 7, :type :ok, :f :get, :key "1", :value "x 1 4 yx 0 16 yx 0 17 y"} {:process 7, :type :invoke, :f :append, :key "9", :value "x 7 14 y"} {:process 7, :type :ok, :f :append, :key "9", :value "x 7 14 y"} {:process 7, :type :invoke, :f :get, :key "2", :value nil} {:process 1, :type :ok, :f :append, :key "0", :value "x 1 6 y"} {:process 1, :type :invoke, :f :get, :key "0", :value nil} {:process 1, :type :ok, :f :get, :key "0", :value "x 8 13 yx 1 6 y"} {:process 1, :type :invoke, :f :get, :key "2", :value nil} {:process 1, :type :ok, :f :get, :key "2", :value "x 0 1 yx 9 3 yx 9 4 yx 9 5 yx 8 1 yx 0 3 yx 0 4 yx 9 8 yx 8 4 yx 7 8 yx 1 1 yx 2 2 y"} {:process 1, :type :invoke, :f :append, :key "9", :value "x 1 7 y"} {:process 7, :type :ok, :f :get, :key "2", :value "x 0 1 yx 9 3 yx 9 4 yx 9 5 yx 8 1 yx 0 3 yx 0 4 yx 9 8 yx 8 4 yx 7 8 yx 1 1 yx 2 2 y"} {:process 7, :type :invoke, :f :append, :key "1", :value "x 7 15 y"} {:process 9, :type :ok, :f :append, :key "8", :value "x 9 11 y"} {:process 9, :type :invoke, :f :append, :key "4", :value "x 9 12 y"} {:process 9, :type :ok, :f :append, :key "4", :value "x 9 12 y"} {:process 9, :type :invoke, :f :get, :key "9", :value nil} {:process 9, :type :ok, :f :get, :key "9", :value "x 6 0 yx 2 0 yx 0 9 yx 0 13 yx 0 14 yx 7 14 y"} {:process 9, :type :invoke, :f :append, :key "5", :value "x 9 13 y"} {:process 1, :type :ok, :f :append, :key "9", :value "x 1 7 y"} {:process 7, :type :ok, :f :append, :key "1", :value "x 7 15 y"} {:process 4, :type :ok, :f :append, :key "2", :value "x 4 4 y"} {:process 5, :type :ok, :f :append, :key "7", :value "x 5 2 y"} {:process 9, :type :ok, :f :append, :key "5", :value "x 9 13 y"} {:process 2, :type :ok, :f :append, :key "9", :value "x 2 3 y"} {:process 3, :type :ok, :f :append, :key "5", :value "x 3 3 y"} {:process 8, :type :ok, :f :put, :key "0", :value "x 8 13 y"} {:process 6, :type :ok, :f :put, :key "2", :value "x 6 6 y"} {:process 0, :type :ok, :f :append, :key "1", :value "x 0 17 y"} {:process 1, :type :invoke, :f :get, :key "2", :value nil} {:process 9, :type :invoke, :f :get, :key "2", :value nil} {:process 0, :type :invoke, :f :get, :key "8", :value nil} {:process 2, :type :invoke, :f :append, :key "9", :value "x 2 0 y"} {:process 3, :type :invoke, :f :append, :key "9", :value "x 3 0 y"} {:process 6, :type :invoke, :f :get, :key "7", :value nil} {:process 4, :type :invoke, :f :append, :key "9", :value "x 4 0 y"} {:process 7, :type :invoke, :f :append, :key "9", :value "x 7 0 y"} {:process 8, :type :invoke, :f :append, :key "5", :value "x 8 0 y"} {:process 5, :type :invoke, :f :append, :key "3", :value "x 5 0 y"} {:process 6, :type :ok, :f :get, :key "7", :value "x 5 2 yx 9 2 yx 9 7 yx 0 7 yx 8 11 y"} {:process 6, :type :invoke, :f :get, :key "5", :value nil} {:process 9, :type :ok, :f :get, :key "2", :value "x 6 6 y"} {:process 9, :type :invoke, :f :get, :key "7", :value nil} {:process 1, :type :ok, :f :get, :key "2", :value "x 6 6 y"} {:process 1, :type :invoke, :f :append, :key "1", :value "x 1 0 y"} {:process 6, :type :ok, :f :get, :key "5", :value "x 3 3 yx 7 2 yx 8 3 yx 6 1 yx 7 10 yx 1 3 yx 8 10 yx 9 13 y"} {:process 6, :type :invoke, :f :get, :key "7", :value nil} {:process 7, :type :ok, :f :append, :key "9", :value "x 7 0 y"} {:process 7, :type :invoke, :f :get, :key "5", :value nil} {:process 7, :type :ok, :f :get, :key "5", :value "x 3 3 yx 7 2 yx 8 3 yx 6 1 yx 7 10 yx 1 3 yx 8 10 yx 9 13 y"} {:process 7, :type :invoke, :f :get, :key "2", :value nil} {:process 9, :type :ok, :f :get, :key "7", :value "x 5 2 yx 9 2 yx 9 7 yx 0 7 yx 8 11 y"} {:process 9, :type :invoke, :f :get, :key "1", :value nil} {:process 6, :type :ok, :f :get, :key "7", :value "x 5 2 yx 9 2 yx 9 7 yx 0 7 yx 8 11 y"} {:process 6, :type :invoke, :f :get, :key "9", :value nil} {:process 9, :type :ok, :f :get, :key "1", :value "x 1 4 yx 0 16 yx 0 17 yx 7 15 y"} {:process 9, :type :invoke, :f :append, :key "5", :value "x 9 0 y"} {:process 6, :type :ok, :f :get, :key "9", :value "x 6 0 yx 2 0 yx 0 9 yx 0 13 yx 0 14 yx 7 14 yx 1 7 yx 2 3 yx 7 0 y"} {:process 6, :type :invoke, :f :append, :key "2", :value "x 6 0 y"} {:process 7, :type :ok, :f :get, :key "2", :value "x 6 6 y"} {:process 7, :type :invoke, :f :put, :key "1", :value "x 7 1 y"} {:process 7, :type :ok, :f :put, :key "1", :value "x 7 1 y"} {:process 7, :type :invoke, :f :append, :key "7", :value "x 7 2 y"} {:process 6, :type :ok, :f :append, :key "2", :value "x 6 0 y"} {:process 6, :type :invoke, :f :get, :key "4", :value nil} {:process 6, :type :ok, :f :get, :key "4", :value "x 8 12 yx 7 13 yx 9 12 y"} {:process 6, :type :invoke, :f :put, :key "0", :value "x 6 1 y"} {:process 4, :type :ok, :f :append, :key "9", :value "x 4 0 y"} {:process 4, :type :invoke, :f :get, :key "7", :value nil} {:process 6, :type :ok, :f :put, :key "0", :value "x 6 1 y"} {:process 6, :type :invoke, :f :append, :key "7", :value "x 6 2 y"} {:process 6, :type :ok, :f :append, :key "7", :value "x 6 2 y"} {:process 6, :type :invoke, :f :append, :key "2", :value "x 6 3 y"} {:process 4, :type :ok, :f :get, :key "7", :value "x 5 2 yx 9 2 yx 9 7 yx 0 7 yx 8 11 yx 7 2 yx 6 2 y"} {:process 4, :type :invoke, :f :append, :key "3", :value "x 4 1 y"} {:process 0, :type :ok, :f :get, :key "8", :value "x 1 0 yx 5 1 yx 7 5 yx 4 3 yx 9 11 y"} {:process 0, :type :invoke, :f :get, :key "6", :value nil} {:process 6, :type :ok, :f :append, :key "2", :value "x 6 3 y"} {:process 6, :type :invoke, :f :append, :key "9", :value "x 6 4 y"} {:process 0, :type :ok, :f :get, :key "6", :value "x 9 10 yx 8 6 yx 8 9 yx 2 1 yx 6 5 y"} {:process 0, :type :invoke, :f :append, :key "2", :value "x 0 0 y"} {:process 6, :type :ok, :f :append, :key "9", :value "x 6 4 y"} {:process 6, :type :invoke, :f :append, :key "5", :value "x 6 5 y"} {:process 5, :type :ok, :f :append, :key "3", :value "x 5 0 y"} {:process 5, :type :invoke, :f :get, :key "2", :value nil} {:process 2, :type :ok, :f :append, :key "9", :value "x 2 0 y"} {:process 2, :type :invoke, :f :append, :key "1", :value "x 2 1 y"} {:process 5, :type :ok, :f :get, :key "2", :value "x 6 6 yx 6 0 yx 6 3 y"} {:process 5, :type :invoke, :f :get, :key "0", :value nil} {:process 5, :type :ok, :f :get, :key "0", :value "x 6 1 y"} {:process 5, :type :invoke, :f :get, :key "0", :value nil} {:process 5, :type :ok, :f :get, :key "0", :value "x 6 1 y"} {:process 5, :type :invoke, :f :append, :key "9", :value "x 5 1 y"} {:process 2, :type :ok, :f :append, :key "1", :value "x 2 1 y"} {:process 2, :type :invoke, :f :append, :key "6", :value "x 2 2 y"} {:process 5, :type :ok, :f :append, :key "9", :value "x 5 1 y"} {:process 5, :type :invoke, :f :append, :key "1", :value "x 5 2 y"} {:process 2, :type :ok, :f :append, :key "6", :value "x 2 2 y"} {:process 2, :type :invoke, :f :get, :key "1", :value nil} {:process 2, :type :ok, :f :get, :key "1", :value "x 7 1 yx 2 1 y"} {:process 2, :type :invoke, :f :get, :key "7", :value nil} {:process 2, :type :ok, :f :get, :key "7", :value "x 5 2 yx 9 2 yx 9 7 yx 0 7 yx 8 11 yx 7 2 yx 6 2 y"} {:process 2, :type :invoke, :f :get, :key "9", :value nil} {:process 2, :type :ok, :f :get, :key "9", :value "x 6 0 yx 2 0 yx 0 9 yx 0 13 yx 0 14 yx 7 14 yx 1 7 yx 2 3 yx 7 0 yx 4 0 yx 6 4 yx 2 0 yx 5 1 y"} {:process 2, :type :invoke, :f :get, :key "8", :value nil} {:process 5, :type :ok, :f :append, :key "1", :value "x 5 2 y"} {:process 5, :type :invoke, :f :append, :key "9", :value "x 5 3 y"} {:process 5, :type :ok, :f :append, :key "9", :value "x 5 3 y"} {:process 5, :type :invoke, :f :get, :key "6", :value nil} {:process 2, :type :ok, :f :get, :key "8", :value "x 1 0 yx 5 1 yx 7 5 yx 4 3 yx 9 11 y"} {:process 2, :type :invoke, :f :get, :key "3", :value nil} {:process 2, :type :ok, :f :get, :key "3", :value "x 9 1 yx 9 6 yx 0 11 yx 6 2 yx 8 5 yx 8 8 yx 6 4 yx 4 1 yx 5 0 y"} {:process 2, :type :invoke, :f :get, :key "7", :value nil} {:process 5, :type :ok, :f :get, :key "6", :value "x 9 10 yx 8 6 yx 8 9 yx 2 1 yx 6 5 yx 2 2 y"} {:process 5, :type :invoke, :f :append, :key "4", :value "x 5 4 y"} {:process 2, :type :ok, :f :get, :key "7", :value "x 5 2 yx 9 2 yx 9 7 yx 0 7 yx 8 11 yx 7 2 yx 6 2 y"} {:process 2, :type :invoke, :f :append, :key "5", :value "x 2 3 y"} {:process 8, :type :ok, :f :append, :key "5", :value "x 8 0 y"} {:process 8, :type :invoke, :f :get, :key "3", :value nil} {:process 8, :type :ok, :f :get, :key "3", :value "x 9 1 yx 9 6 yx 0 11 yx 6 2 yx 8 5 yx 8 8 yx 6 4 yx 4 1 yx 5 0 y"} {:process 8, :type :invoke, :f :get, :key "5", :value nil} {:process 8, :type :ok, :f :get, :key "5", :value "x 3 3 yx 7 2 yx 8 3 yx 6 1 yx 7 10 yx 1 3 yx 8 10 yx 9 13 yx 8 0 y"} {:process 8, :type :invoke, :f :append, :key "1", :value "x 8 1 y"} {:process 8, :type :ok, :f :append, :key "1", :value "x 8 1 y"} {:process 8, :type :invoke, :f :get, :key "7", :value nil} {:process 8, :type :ok, :f :get, :key "7", :value "x 5 2 yx 9 2 yx 9 7 yx 0 7 yx 8 11 yx 7 2 yx 6 2 y"} {:process 8, :type :invoke, :f :get, :key "5", :value nil} {:process 8, :type :ok, :f :get, :key "5", :value "x 3 3 yx 7 2 yx 8 3 yx 6 1 yx 7 10 yx 1 3 yx 8 10 yx 9 13 yx 8 0 y"} {:process 8, :type :invoke, :f :get, :key "9", :value nil} {:process 8, :type :ok, :f :get, :key "9", :value "x 6 0 yx 2 0 yx 0 9 yx 0 13 yx 0 14 yx 7 14 yx 1 7 yx 2 3 yx 7 0 yx 4 0 yx 6 4 yx 2 0 yx 5 1 yx 5 3 yx 3 0 y"} {:process 8, :type :invoke, :f :get, :key "8", :value nil} {:process 8, :type :ok, :f :get, :key "8", :value "x 1 0 yx 5 1 yx 7 5 yx 4 3 yx 9 11 y"} {:process 8, :type :invoke, :f :get, :key "3", :value nil} {:process 8, :type :ok, :f :get, :key "3", :value "x 9 1 yx 9 6 yx 0 11 yx 6 2 yx 8 5 yx 8 8 yx 6 4 yx 4 1 yx 5 0 y"} {:process 8, :type :invoke, :f :get, :key "0", :value nil} {:process 0, :type :ok, :f :append, :key "2", :value "x 0 0 y"} {:process 0, :type :invoke, :f :put, :key "2", :value "x 0 1 y"} {:process 8, :type :ok, :f :get, :key "0", :value "x 6 1 y"} {:process 8, :type :invoke, :f :append, :key "4", :value "x 8 2 y"} {:process 9, :type :ok, :f :append, :key "5", :value "x 9 0 y"} {:process 9, :type :invoke, :f :get, :key "0", :value nil} {:process 9, :type :ok, :f :get, :key "0", :value "x 6 1 y"} {:process 9, :type :invoke, :f :get, :key "2", :value nil} {:process 9, :type :ok, :f :get, :key "2", :value "x 6 6 yx 6 0 yx 6 3 yx 0 0 y"} {:process 9, :type :invoke, :f :get, :key "2", :value nil} {:process 9, :type :ok, :f :get, :key "2", :value "x 6 6 yx 6 0 yx 6 3 yx 0 0 y"} {:process 9, :type :invoke, :f :append, :key "4", :value "x 9 1 y"} {:process 0, :type :ok, :f :put, :key "2", :value "x 0 1 y"} {:process 0, :type :invoke, :f :get, :key "2", :value nil} {:process 0, :type :ok, :f :get, :key "2", :value "x 0 1 y"} {:process 0, :type :invoke, :f :get, :key "2", :value nil} {:process 0, :type :ok, :f :get, :key "2", :value "x 0 1 y"} {:process 0, :type :invoke, :f :append, :key "3", :value "x 0 2 y"} {:process 6, :type :ok, :f :append, :key "5", :value "x 6 5 y"} {:process 6, :type :invoke, :f :append, :key "2", :value "x 6 6 y"} {:process 6, :type :ok, :f :append, :key "2", :value "x 6 6 y"} {:process 6, :type :invoke, :f :get, :key "6", :value nil} {:process 6, :type :ok, :f :get, :key "6", :value "x 9 10 yx 8 6 yx 8 9 yx 2 1 yx 6 5 yx 2 2 y"} {:process 6, :type :invoke, :f :append, :key "7", :value "x 6 7 y"} {:process 6, :type :ok, :f :append, :key "7", :value "x 6 7 y"} {:process 6, :type :invoke, :f :append, :key "3", :value "x 6 8 y"} {:process 6, :type :ok, :f :append, :key "3", :value "x 6 8 y"} {:process 6, :type :invoke, :f :get, :key "7", :value nil} {:process 6, :type :ok, :f :get, :key "7", :value "x 5 2 yx 9 2 yx 9 7 yx 0 7 yx 8 11 yx 7 2 yx 6 2 yx 6 7 y"} {:process 6, :type :invoke, :f :append, :key "5", :value "x 6 9 y"} {:process 8, :type :ok, :f :append, :key "4", :value "x 8 2 y"} {:process 8, :type :invoke, :f :append, :key "1", :value "x 8 3 y"} {:process 6, :type :ok, :f :append, :key "5", :value "x 6 9 y"} {:process 6, :type :invoke, :f :get, :key "6", :value nil} {:process 6, :type :ok, :f :get, :key "6", :value "x 9 10 yx 8 6 yx 8 9 yx 2 1 yx 6 5 yx 2 2 y"} {:process 6, :type :invoke, :f :append, :key "9", :value "x 6 10 y"} {:process 8, :type :ok, :f :append, :key "1", :value "x 8 3 y"} {:process 8, :type :invoke, :f :append, :key "6", :value "x 8 4 y"} {:process 6, :type :ok, :f :append, :key "9", :value "x 6 10 y"} {:process 6, :type :invoke, :f :get, :key "8", :value nil} {:process 3, :type :ok, :f :append, :key "9", :value "x 3 0 y"} {:process 3, :type :invoke, :f :append, :key "5", :value "x 3 1 y"} {:process 7, :type :ok, :f :append, :key "7", :value "x 7 2 y"} {:process 7, :type :invoke, :f :append, :key "8", :value "x 7 3 y"} {:process 6, :type :ok, :f :get, :key "8", :value "x 1 0 yx 5 1 yx 7 5 yx 4 3 yx 9 11 y"} {:process 6, :type :invoke, :f :get, :key "5", :value nil} {:process 8, :type :ok, :f :append, :key "6", :value "x 8 4 y"} {:process 8, :type :invoke, :f :get, :key "1", :value nil} {:process 6, :type :ok, :f :get, :key "5", :value "x 3 3 yx 7 2 yx 8 3 yx 6 1 yx 7 10 yx 1 3 yx 8 10 yx 9 13 yx 8 0 yx 9 0 yx 6 5 yx 6 9 y"} {:process 6, :type :invoke, :f :get, :key "5", :value nil} {:process 7, :type :ok, :f :append, :key "8", :value "x 7 3 y"} {:process 7, :type :invoke, :f :get, :key "0", :value nil} {:process 6, :type :ok, :f :get, :key "5", :value "x 3 3 yx 7 2 yx 8 3 yx 6 1 yx 7 10 yx 1 3 yx 8 10 yx 9 13 yx 8 0 yx 9 0 yx 6 5 yx 6 9 y"} {:process 6, :type :invoke, :f :append, :key "7", :value "x 6 11 y"} {:process 7, :type :ok, :f :get, :key "0", :value "x 6 1 y"} {:process 7, :type :invoke, :f :append, :key "5", :value "x 7 4 y"} {:process 3, :type :ok, :f :append, :key "5", :value "x 3 1 y"} {:process 3, :type :invoke, :f :get, :key "5", :value nil} {:process 6, :type :ok, :f :append, :key "7", :value "x 6 11 y"} {:process 6, :type :invoke, :f :get, :key "0", :value nil} {:process 7, :type :ok, :f :append, :key "5", :value "x 7 4 y"} {:process 7, :type :invoke, :f :get, :key "3", :value nil} {:process 5, :type :ok, :f :append, :key "4", :value "x 5 4 y"} {:process 5, :type :invoke, :f :append, :key "7", :value "x 5 5 y"} {:process 3, :type :ok, :f :get, :key "5", :value "x 3 3 yx 7 2 yx 8 3 yx 6 1 yx 7 10 yx 1 3 yx 8 10 yx 9 13 yx 8 0 yx 9 0 yx 6 5 yx 6 9 yx 3 1 yx 7 4 y"} {:process 3, :type :invoke, :f :append, :key "0", :value "x 3 2 y"} {:process 7, :type :ok, :f :get, :key "3", :value "x 9 1 yx 9 6 yx 0 11 yx 6 2 yx 8 5 yx 8 8 yx 6 4 yx 4 1 yx 5 0 yx 0 2 yx 6 8 y"} {:process 7, :type :invoke, :f :get, :key "6", :value nil} {:process 7, :type :ok, :f :get, :key "6", :value "x 9 10 yx 8 6 yx 8 9 yx 2 1 yx 6 5 yx 2 2 yx 8 4 y"} {:process 7, :type :invoke, :f :get, :key "5", :value nil} {:process 5, :type :ok, :f :append, :key "7", :value "x 5 5 y"} {:process 5, :type :invoke, :f :append, :key "5", :value "x 5 6 y"} {:process 3, :type :ok, :f :append, :key "0", :value "x 3 2 y"} {:process 3, :type :invoke, :f :get, :key "8", :value nil} {:process 5, :type :ok, :f :append, :key "5", :value "x 5 6 y"} {:process 5, :type :invoke, :f :append, :key "1", :value "x 5 7 y"} {:process 2, :type :ok, :f :append, :key "5", :value "x 2 3 y"} {:process 2, :type :invoke, :f :get, :key "3", :value nil} {:process 3, :type :ok, :f :get, :key "8", :value "x 1 0 yx 5 1 yx 7 5 yx 4 3 yx 9 11 yx 7 3 y"} {:process 3, :type :invoke, :f :get, :key "1", :value nil} {:process 8, :type :ok, :f :get, :key "1", :value "x 7 1 yx 2 1 yx 5 2 yx 1 0 yx 8 1 yx 8 3 y"} {:process 8, :type :invoke, :f :append, :key "7", :value "x 8 5 y"} {:process 2, :type :ok, :f :get, :key "3", :value "x 9 1 yx 9 6 yx 0 11 yx 6 2 yx 8 5 yx 8 8 yx 6 4 yx 4 1 yx 5 0 yx 0 2 yx 6 8 y"} {:process 2, :type :invoke, :f :put, :key "4", :value "x 2 4 y"} {:process 5, :type :ok, :f :append, :key "1", :value "x 5 7 y"} {:process 5, :type :invoke, :f :get, :key "4", :value nil} {:process 5, :type :ok, :f :get, :key "4", :value "x 8 12 yx 7 13 yx 9 12 yx 8 2 yx 5 4 y"} {:process 5, :type :invoke, :f :append, :key "6", :value "x 5 8 y"} {:process 5, :type :ok, :f :append, :key "6", :value "x 5 8 y"} {:process 5, :type :invoke, :f :append, :key "1", :value "x 5 9 y"} {:process 6, :type :ok, :f :get, :key "0", :value "x 6 1 yx 3 2 y"} {:process 6, :type :invoke, :f :append, :key "3", :value "x 6 12 y"} {:process 7, :type :ok, :f :get, :key "5", :value "x 3 3 yx 7 2 yx 8 3 yx 6 1 yx 7 10 yx 1 3 yx 8 10 yx 9 13 yx 8 0 yx 9 0 y"} {:process 7, :type :invoke, :f :get, :key "1", :value nil} {:process 7, :type :ok, :f :get, :key "1", :value "x 7 1 yx 2 1 yx 5 2 yx 1 0 yx 8 1 y"} {:process 7, :type :invoke, :f :append, :key "4", :value "x 7 5 y"} {:process 3, :type :ok, :f :get, :key "1", :value "x 7 1 yx 2 1 yx 5 2 yx 1 0 yx 8 1 yx 8 3 yx 5 7 y"} {:process 3, :type :invoke, :f :get, :key "3", :value nil} {:process 3, :type :ok, :f :get, :key "3", :value "x 9 1 yx 9 6 yx 0 11 yx 6 2 yx 8 5 yx 8 8 yx 6 4 yx 4 1 yx 5 0 yx 0 2 yx 6 8 y"} {:process 3, :type :invoke, :f :append, :key "5", :value "x 3 3 y"} {:process 9, :type :ok, :f :append, :key "4", :value "x 9 1 y"} {:process 9, :type :invoke, :f :put, :key "2", :value "x 9 2 y"} {:process 3, :type :ok, :f :append, :key "5", :value "x 3 3 y"} {:process 3, :type :invoke, :f :append, :key "2", :value "x 3 4 y"} {:process 3, :type :ok, :f :append, :key "2", :value "x 3 4 y"} {:process 3, :type :invoke, :f :get, :key "1", :value nil} {:process 3, :type :ok, :f :get, :key "1", :value "x 7 1 yx 2 1 yx 5 2 yx 1 0 yx 8 1 yx 8 3 yx 5 7 yx 5 9 y"} {:process 3, :type :invoke, :f :get, :key "6", :value nil} {:process 2, :type :ok, :f :put, :key "4", :value "x 2 4 y"} {:process 2, :type :invoke, :f :get, :key "1", :value nil} {:process 2, :type :ok, :f :get, :key "1", :value "x 7 1 yx 2 1 yx 5 2 yx 1 0 yx 8 1 yx 8 3 yx 5 7 yx 5 9 y"} {:process 2, :type :invoke, :f :get, :key "9", :value nil} {:process 2, :type :ok, :f :get, :key "9", :value "x 6 0 yx 2 0 yx 0 9 yx 0 13 yx 0 14 yx 7 14 yx 1 7 yx 2 3 yx 7 0 yx 4 0 yx 6 4 yx 2 0 yx 5 1 yx 5 3 yx 3 0 yx 6 10 y"} {:process 2, :type :invoke, :f :append, :key "3", :value "x 2 5 y"} {:process 5, :type :ok, :f :append, :key "1", :value "x 5 9 y"} {:process 5, :type :invoke, :f :append, :key "4", :value "x 5 10 y"} {:process 2, :type :ok, :f :append, :key "3", :value "x 2 5 y"} {:process 2, :type :invoke, :f :get, :key "1", :value nil} {:process 2, :type :ok, :f :get, :key "1", :value "x 7 1 yx 2 1 yx 5 2 yx 1 0 yx 8 1 yx 8 3 yx 5 7 yx 5 9 y"} {:process 2, :type :invoke, :f :append, :key "6", :value "x 2 6 y"} {:process 2, :type :ok, :f :append, :key "6", :value "x 2 6 y"} {:process 2, :type :invoke, :f :append, :key "6", :value "x 2 7 y"} {:process 3, :type :ok, :f :get, :key "6", :value "x 9 10 yx 8 6 yx 8 9 yx 2 1 yx 6 5 yx 2 2 yx 8 4 yx 5 8 y"} {:process 3, :type :invoke, :f :put, :key "6", :value "x 3 5 y"} {:process 2, :type :ok, :f :append, :key "6", :value "x 2 7 y"} {:process 2, :type :invoke, :f :get, :key "9", :value nil} {:process 2, :type :ok, :f :get, :key "9", :value "x 6 0 yx 2 0 yx 0 9 yx 0 13 yx 0 14 yx 7 14 yx 1 7 yx 2 3 yx 7 0 yx 4 0 yx 6 4 yx 2 0 yx 5 1 yx 5 3 yx 3 0 yx 6 10 y"} {:process 2, :type :invoke, :f :append, :key "4", :value "x 2 8 y"} {:process 9, :type :ok, :f :put, :key "2", :value "x 9 2 y"} {:process 9, :type :invoke, :f :append, :key "1", :value "x 9 3 y"} {:process 2, :type :ok, :f :append, :key "4", :value "x 2 8 y"} {:process 2, :type :invoke, :f :get, :key "7", :value nil} {:process 9, :type :ok, :f :append, :key "1", :value "x 9 3 y"} {:process 9, :type :invoke, :f :append, :key "7", :value "x 9 4 y"} {:process 2, :type :ok, :f :get, :key "7", :value "x 5 2 yx 9 2 yx 9 7 yx 0 7 yx 8 11 yx 7 2 yx 6 2 yx 6 7 yx 6 11 yx 5 5 y"} {:process 2, :type :invoke, :f :get, :key "3", :value nil} {:process 2, :type :ok, :f :get, :key "3", :value "x 9 1 yx 9 6 yx 0 11 yx 6 2 yx 8 5 yx 8 8 yx 6 4 yx 4 1 yx 5 0 yx 0 2 yx 6 8 yx 2 5 y"} {:process 2, :type :invoke, :f :append, :key "5", :value "x 2 9 y"} {:process 6, :type :ok, :f :append, :key "3", :value "x 6 12 y"} {:process 6, :type :invoke, :f :append, :key "9", :value "x 6 13 y"} {:process 6, :type :ok, :f :append, :key "9", :value "x 6 13 y"} {:process 6, :type :invoke, :f :append, :key "8", :value "x 6 14 y"} {:process 6, :type :ok, :f :append, :key "8", :value "x 6 14 y"} {:process 6, :type :invoke, :f :get, :key "1", :value nil} {:process 6, :type :ok, :f :get, :key "1", :value "x 7 1 yx 2 1 yx 5 2 yx 1 0 yx 8 1 yx 8 3 yx 5 7 yx 5 9 yx 9 3 y"} {:process 6, :type :invoke, :f :append, :key "1", :value "x 6 15 y"} {:process 6, :type :ok, :f :append, :key "1", :value "x 6 15 y"} {:process 6, :type :invoke, :f :get, :key "4", :value nil} {:process 6, :type :ok, :f :get, :key "4", :value "x 2 4 yx 9 1 yx 2 8 y"} {:process 6, :type :invoke, :f :get, :key "1", :value nil} {:process 6, :type :ok, :f :get, :key "1", :value "x 7 1 yx 2 1 yx 5 2 yx 1 0 yx 8 1 yx 8 3 yx 5 7 yx 5 9 yx 9 3 yx 6 15 y"} {:process 6, :type :invoke, :f :get, :key "9", :value nil} {:process 6, :type :ok, :f :get, :key "9", :value "x 6 0 yx 2 0 yx 0 9 yx 0 13 yx 0 14 yx 7 14 yx 1 7 yx 2 3 yx 7 0 yx 4 0 yx 6 4 yx 2 0 yx 5 1 yx 5 3 yx 3 0 yx 6 10 yx 6 13 y"} {:process 6, :type :invoke, :f :append, :key "5", :value "x 6 16 y"} {:process 6, :type :ok, :f :append, :key "5", :value "x 6 16 y"} {:process 6, :type :invoke, :f :append, :key "6", :value "x 6 17 y"} {:process 1, :type :ok, :f :append, :key "1", :value "x 1 0 y"} {:process 1, :type :invoke, :f :append, :key "9", :value "x 1 1 y"} {:process 6, :type :ok, :f :append, :key "6", :value "x 6 17 y"} {:process 6, :type :invoke, :f :get, :key "0", :value nil} {:process 3, :type :ok, :f :put, :key "6", :value "x 3 5 y"} {:process 3, :type :invoke, :f :get, :key "1", :value nil} {:process 5, :type :ok, :f :append, :key "4", :value "x 5 10 y"} {:process 5, :type :invoke, :f :get, :key "2", :value nil} {:process 3, :type :ok, :f :get, :key "1", :value "x 7 1 yx 2 1 yx 5 2 yx 1 0 yx 8 1 yx 8 3 yx 5 7 yx 5 9 yx 9 3 yx 6 15 y"} {:process 3, :type :invoke, :f :get, :key "0", :value nil} {:process 3, :type :ok, :f :get, :key "0", :value "x 6 1 yx 3 2 y"} {:process 3, :type :invoke, :f :append, :key "6", :value "x 3 6 y"} {:process 5, :type :ok, :f :get, :key "2", :value "x 9 2 yx 3 4 y"} {:process 5, :type :invoke, :f :get, :key "4", :value nil} {:process 5, :type :ok, :f :get, :key "4", :value "x 2 4 yx 9 1 yx 2 8 yx 5 10 y"} {:process 5, :type :invoke, :f :get, :key "2", :value nil} {:process 5, :type :ok, :f :get, :key "2", :value "x 9 2 yx 3 4 y"} {:process 5, :type :invoke, :f :append, :key "3", :value "x 5 11 y"} {:process 3, :type :ok, :f :append, :key "6", :value "x 3 6 y"} {:process 3, :type :invoke, :f :get, :key "4", :value nil} {:process 3, :type :ok, :f :get, :key "4", :value "x 2 4 yx 9 1 yx 2 8 yx 5 10 y"} {:process 3, :type :invoke, :f :append, :key "9", :value "x 3 7 y"} {:process 5, :type :ok, :f :append, :key "3", :value "x 5 11 y"} {:process 5, :type :invoke, :f :append, :key "2", :value "x 5 12 y"} {:process 5, :type :ok, :f :append, :key "2", :value "x 5 12 y"} {:process 5, :type :invoke, :f :append, :key "6", :value "x 5 13 y"} {:process 5, :type :ok, :f :append, :key "6", :value "x 5 13 y"} {:process 5, :type :invoke, :f :put, :key "9", :value "x 5 14 y"} {:process 5, :type :ok, :f :put, :key "9", :value "x 5 14 y"} {:process 5, :type :invoke, :f :append, :key "0", :value "x 5 15 y"} {:process 5, :type :ok, :f :append, :key "0", :value "x 5 15 y"} {:process 5, :type :invoke, :f :append, :key "8", :value "x 5 16 y"} {:process 2, :type :ok, :f :append, :key "5", :value "x 2 9 y"} {:process 2, :type :invoke, :f :append, :key "5", :value "x 2 10 y"} {:process 6, :type :ok, :f :get, :key "0", :value "x 6 1 yx 3 2 y"} {:process 6, :type :invoke, :f :get, :key "2", :value nil} {:process 5, :type :ok, :f :append, :key "8", :value "x 5 16 y"} {:process 5, :type :invoke, :f :append, :key "8", :value "x 5 17 y"} {:process 6, :type :ok, :f :get, :key "2", :value "x 9 2 yx 3 4 yx 5 12 y"} {:process 6, :type :invoke, :f :get, :key "2", :value nil} {:process 2, :type :ok, :f :append, :key "5", :value "x 2 10 y"} {:process 2, :type :invoke, :f :get, :key "3", :value nil} {:process 6, :type :ok, :f :get, :key "2", :value "x 9 2 yx 3 4 yx 5 12 y"} {:process 6, :type :invoke, :f :get, :key "0", :value nil} {:process 2, :type :ok, :f :get, :key "3", :value "x 9 1 yx 9 6 yx 0 11 yx 6 2 yx 8 5 yx 8 8 yx 6 4 yx 4 1 yx 5 0 yx 0 2 yx 6 8 yx 2 5 yx 6 12 yx 5 11 y"} {:process 2, :type :invoke, :f :put, :key "5", :value "x 2 11 y"} {:process 5, :type :ok, :f :append, :key "8", :value "x 5 17 y"} {:process 5, :type :invoke, :f :get, :key "9", :value nil} {:process 6, :type :ok, :f :get, :key "0", :value "x 6 1 yx 3 2 yx 5 15 y"} {:process 6, :type :invoke, :f :get, :key "5", :value nil} {:process 6, :type :ok, :f :get, :key "5", :value "x 3 3 yx 7 2 yx 8 3 yx 6 1 yx 7 10 yx 1 3 yx 8 10 yx 9 13 yx 8 0 yx 9 0 yx 6 5 yx 6 9 yx 3 1 yx 7 4 yx 5 6 yx 2 3 yx 3 3 yx 6 16 yx 2 9 y"} {:process 6, :type :invoke, :f :append, :key "9", :value "x 6 18 y"} {:process 2, :type :ok, :f :put, :key "5", :value "x 2 11 y"} {:process 2, :type :invoke, :f :get, :key "9", :value nil} {:process 2, :type :ok, :f :get, :key "9", :value "x 5 14 y"} {:process 2, :type :invoke, :f :append, :key "2", :value "x 2 12 y"} {:process 2, :type :ok, :f :append, :key "2", :value "x 2 12 y"} {:process 2, :type :invoke, :f :append, :key "3", :value "x 2 13 y"} {:process 5, :type :ok, :f :get, :key "9", :value "x 5 14 y"} {:process 5, :type :invoke, :f :get, :key "5", :value nil} {:process 5, :type :ok, :f :get, :key "5", :value "x 2 11 y"} {:process 5, :type :invoke, :f :append, :key "3", :value "x 5 18 y"} {:process 0, :type :ok, :f :append, :key "3", :value "x 0 2 y"} {:process 0, :type :invoke, :f :append, :key "6", :value "x 0 3 y"} {:process 4, :type :ok, :f :append, :key "3", :value "x 4 1 y"} {:process 4, :type :invoke, :f :append, :key "2", :value "x 4 2 y"} {:process 0, :type :ok, :f :append, :key "6", :value "x 0 3 y"} {:process 0, :type :invoke, :f :get, :key "0", :value nil} {:process 0, :type :ok, :f :get, :key "0", :value "x 6 1 yx 3 2 yx 5 15 y"} {:process 0, :type :invoke, :f :get, :key "4", :value nil} {:process 0, :type :ok, :f :get, :key "4", :value "x 2 4 yx 9 1 yx 2 8 yx 5 10 y"} {:process 0, :type :invoke, :f :append, :key "1", :value "x 0 4 y"} {:process 6, :type :ok, :f :append, :key "9", :value "x 6 18 y"} {:process 6, :type :invoke, :f :get, :key "3", :value nil} {:process 6, :type :ok, :f :get, :key "3", :value "x 9 1 yx 9 6 yx 0 11 yx 6 2 yx 8 5 yx 8 8 yx 6 4 yx 4 1 yx 5 0 yx 0 2 yx 6 8 yx 2 5 yx 6 12 yx 5 11 y"} {:process 6, :type :invoke, :f :put, :key "8", :value "x 6 19 y"} {:process 1, :type :ok, :f :append, :key "9", :value "x 1 1 y"} {:process 1, :type :invoke, :f :append, :key "2", :value "x 1 2 y"} {:process 1, :type :ok, :f :append, :key "2", :value "x 1 2 y"} {:process 1, :type :invoke, :f :append, :key "4", :value "x 1 3 y"} {:process 2, :type :ok, :f :append, :key "3", :value "x 2 13 y"} {:process 2, :type :invoke, :f :append, :key "2", :value "x 2 14 y"} {:process 8, :type :ok, :f :append, :key "7", :value "x 8 5 y"} {:process 8, :type :invoke, :f :append, :key "3", :value "x 8 6 y"} {:process 8, :type :ok, :f :append, :key "3", :value "x 8 6 y"} {:process 8, :type :invoke, :f :put, :key "4", :value "x 8 7 y"} {:process 8, :type :ok, :f :put, :key "4", :value "x 8 7 y"} {:process 8, :type :invoke, :f :append, :key "6", :value "x 8 8 y"} {:process 8, :type :ok, :f :append, :key "6", :value "x 8 8 y"} {:process 8, :type :invoke, :f :append, :key "5", :value "x 8 9 y"} {:process 5, :type :ok, :f :append, :key "3", :value "x 5 18 y"} {:process 5, :type :invoke, :f :get, :key "1", :value nil} {:process 5, :type :ok, :f :get, :key "1", :value "x 7 1 yx 2 1 yx 5 2 yx 1 0 yx 8 1 yx 8 3 yx 5 7 yx 5 9 yx 9 3 yx 6 15 y"} {:process 5, :type :invoke, :f :get, :key "5", :value nil} {:process 8, :type :ok, :f :append, :key "5", :value "x 8 9 y"} {:process 8, :type :invoke, :f :get, :key "1", :value nil} {:process 5, :type :ok, :f :get, :key "5", :value "x 2 11 yx 8 9 y"} {:process 5, :type :invoke, :f :get, :key "3", :value nil} {:process 5, :type :ok, :f :get, :key "3", :value "x 9 1 yx 9 6 yx 0 11 yx 6 2 yx 8 5 yx 8 8 yx 6 4 yx 4 1 yx 5 0 yx 0 2 yx 6 8 yx 2 5 yx 6 12 yx 5 11 yx 2 13 yx 8 6 yx 5 18 y"} {:process 5, :type :invoke, :f :append, :key "8", :value "x 5 19 y"} {:process 5, :type :ok, :f :append, :key "8", :value "x 5 19 y"} {:process 5, :type :invoke, :f :append, :key "6", :value "x 5 20 y"} {:process 5, :type :ok, :f :append, :key "6", :value "x 5 20 y"} {:process 5, :type :invoke, :f :get, :key "3", :value nil} {:process 5, :type :ok, :f :get, :key "3", :value "x 9 1 yx 9 6 yx 0 11 yx 6 2 yx 8 5 yx 8 8 yx 6 4 yx 4 1 yx 5 0 yx 0 2 yx 6 8 yx 2 5 yx 6 12 yx 5 11 yx 2 13 yx 8 6 yx 5 18 y"} {:process 5, :type :invoke, :f :append, :key "4", :value "x 5 21 y"} {:process 9, :type :ok, :f :append, :key "7", :value "x 9 4 y"} {:process 9, :type :invoke, :f :get, :key "9", :value nil} {:process 5, :type :ok, :f :append, :key "4", :value "x 5 21 y"} {:process 5, :type :invoke, :f :append, :key "4", :value "x 5 22 y"} {:process 9, :type :ok, :f :get, :key "9", :value "x 5 14 yx 6 18 yx 1 1 y"} {:process 9, :type :invoke, :f :get, :key "8", :value nil} {:process 8, :type :ok, :f :get, :key "1", :value "x 7 1 yx 2 1 yx 5 2 yx 1 0 yx 8 1 yx 8 3 yx 5 7 yx 5 9 yx 9 3 yx 6 15 y"} {:process 8, :type :invoke, :f :get, :key "3", :value nil} {:process 4, :type :ok, :f :append, :key "2", :value "x 4 2 y"} {:process 4, :type :invoke, :f :get, :key "4", :value nil} {:process 5, :type :ok, :f :append, :key "4", :value "x 5 22 y"} {:process 5, :type :invoke, :f :get, :key "5", :value nil} {:process 4, :type :ok, :f :get, :key "4", :value "x 8 7 yx 5 21 yx 5 22 y"} {:process 4, :type :invoke, :f :append, :key "5", :value "x 4 3 y"} {:process 9, :type :ok, :f :get, :key "8", :value "x 6 19 yx 5 19 y"} {:process 9, :type :invoke, :f :get, :key "3", :value nil} {:process 0, :type :ok, :f :append, :key "1", :value "x 0 4 y"} {:process 0, :type :invoke, :f :get, :key "3", :value nil} {:process 0, :type :ok, :f :get, :key "3", :value "x 9 1 yx 9 6 yx 0 11 yx 6 2 yx 8 5 yx 8 8 yx 6 4 yx 4 1 yx 5 0 yx 0 2 yx 6 8 yx 2 5 yx 6 12 yx 5 11 yx 2 13 yx 8 6 yx 5 18 y"} {:process 0, :type :invoke, :f :append, :key "2", :value "x 0 5 y"} {:process 4, :type :ok, :f :append, :key "5", :value "x 4 3 y"} {:process 4, :type :invoke, :f :get, :key "2", :value nil} {:process 9, :type :ok, :f :get, :key "3", :value "x 9 1 yx 9 6 yx 0 11 yx 6 2 yx 8 5 yx 8 8 yx 6 4 yx 4 1 yx 5 0 yx 0 2 yx 6 8 yx 2 5 yx 6 12 yx 5 11 yx 2 13 yx 8 6 yx 5 18 y"} {:process 9, :type :invoke, :f :append, :key "6", :value "x 9 5 y"} {:process 4, :type :ok, :f :get, :key "2", :value "x 9 2 yx 3 4 yx 5 12 yx 2 12 yx 4 2 yx 1 2 y"} {:process 4, :type :invoke, :f :get, :key "2", :value nil} {:process 4, :type :ok, :f :get, :key "2", :value "x 9 2 yx 3 4 yx 5 12 yx 2 12 yx 4 2 yx 1 2 y"} {:process 4, :type :invoke, :f :append, :key "4", :value "x 4 4 y"} {:process 9, :type :ok, :f :append, :key "6", :value "x 9 5 y"} {:process 9, :type :invoke, :f :append, :key "0", :value "x 9 6 y"} {:process 0, :type :ok, :f :append, :key "2", :value "x 0 5 y"} {:process 0, :type :invoke, :f :get, :key "6", :value nil} {:process 0, :type :ok, :f :get, :key "6", :value "x 3 5 yx 3 6 yx 5 13 yx 0 3 yx 8 8 yx 5 20 yx 9 5 y"} {:process 0, :type :invoke, :f :append, :key "2", :value "x 0 6 y"} {:process 7, :type :ok, :f :append, :key "4", :value "x 7 5 y"} {:process 7, :type :invoke, :f :append, :key "5", :value "x 7 6 y"} {:process 4, :type :ok, :f :append, :key "4", :value "x 4 4 y"} {:process 4, :type :invoke, :f :append, :key "4", :value "x 4 5 y"} {:process 7, :type :ok, :f :append, :key "5", :value "x 7 6 y"} {:process 7, :type :invoke, :f :get, :key "1", :value nil} {:process 0, :type :ok, :f :append, :key "2", :value "x 0 6 y"} {:process 0, :type :invoke, :f :append, :key "9", :value "x 0 7 y"} {:process 4, :type :ok, :f :append, :key "4", :value "x 4 5 y"} {:process 4, :type :invoke, :f :get, :key "7", :value nil} {:process 9, :type :ok, :f :append, :key "0", :value "x 9 6 y"} {:process 9, :type :invoke, :f :append, :key "7", :value "x 9 7 y"} {:process 0, :type :ok, :f :append, :key "9", :value "x 0 7 y"} {:process 0, :type :invoke, :f :append, :key "3", :value "x 0 8 y"} {:process 4, :type :ok, :f :get, :key "7", :value "x 5 2 yx 9 2 yx 9 7 yx 0 7 yx 8 11 yx 7 2 yx 6 2 yx 6 7 yx 6 11 yx 5 5 yx 9 4 yx 8 5 y"} {:process 4, :type :invoke, :f :get, :key "7", :value nil} {:process 4, :type :ok, :f :get, :key "7", :value "x 5 2 yx 9 2 yx 9 7 yx 0 7 yx 8 11 yx 7 2 yx 6 2 yx 6 7 yx 6 11 yx 5 5 yx 9 4 yx 8 5 y"} {:process 4, :type :invoke, :f :get, :key "5", :value nil} {:process 9, :type :ok, :f :append, :key "7", :value "x 9 7 y"} {:process 9, :type :invoke, :f :append, :key "6", :value "x 9 8 y"} {:process 0, :type :ok, :f :append, :key "3", :value "x 0 8 y"} {:process 0, :type :invoke, :f :get, :key "2", :value nil} {:process 0, :type :ok, :f :get, :key "2", :value "x 9 2 yx 3 4 yx 5 12 yx 2 12 yx 4 2 yx 1 2 yx 0 5 yx 0 6 y"} {:process 0, :type :invoke, :f :get, :key "1", :value nil} {:process 0, :type :ok, :f :get, :key "1", :value "x 7 1 yx 2 1 yx 5 2 yx 1 0 yx 8 1 yx 8 3 yx 5 7 yx 5 9 yx 9 3 yx 6 15 yx 0 4 y"} {:process 0, :type :invoke, :f :get, :key "5", :value nil} {:process 5, :type :ok, :f :get, :key "5", :value "x 2 11 yx 8 9 yx 4 3 yx 7 6 y"} {:process 5, :type :invoke, :f :get, :key "7", :value nil} {:process 4, :type :ok, :f :get, :key "5", :value "x 2 11 yx 8 9 yx 4 3 yx 7 6 y"} {:process 4, :type :invoke, :f :get, :key "7", :value nil} {:process 4, :type :ok, :f :get, :key "7", :value "x 5 2 yx 9 2 yx 9 7 yx 0 7 yx 8 11 yx 7 2 yx 6 2 yx 6 7 yx 6 11 yx 5 5 yx 9 4 yx 8 5 yx 9 7 y"} {:process 4, :type :invoke, :f :append, :key "2", :value "x 4 6 y"} {:process 0, :type :ok, :f :get, :key "5", :value "x 2 11 yx 8 9 yx 4 3 yx 7 6 y"} {:process 0, :type :invoke, :f :get, :key "4", :value nil} {:process 8, :type :ok, :f :get, :key "3", :value "x 9 1 yx 9 6 yx 0 11 yx 6 2 yx 8 5 yx 8 8 yx 6 4 yx 4 1 yx 5 0 yx 0 2 yx 6 8 yx 2 5 yx 6 12 yx 5 11 yx 2 13 yx 8 6 yx 5 18 y"} {:process 8, :type :invoke, :f :append, :key "6", :value "x 8 10 y"} {:process 0, :type :ok, :f :get, :key "4", :value "x 8 7 yx 5 21 yx 5 22 yx 7 5 yx 4 4 yx 4 5 y"} {:process 0, :type :invoke, :f :append, :key "8", :value "x 0 9 y"} {:process 9, :type :ok, :f :append, :key "6", :value "x 9 8 y"} {:process 9, :type :invoke, :f :append, :key "8", :value "x 9 9 y"} {:process 4, :type :ok, :f :append, :key "2", :value "x 4 6 y"} {:process 4, :type :invoke, :f :append, :key "5", :value "x 4 7 y"} {:process 0, :type :ok, :f :append, :key "8", :value "x 0 9 y"} {:process 0, :type :invoke, :f :get, :key "9", :value nil} {:process 9, :type :ok, :f :append, :key "8", :value "x 9 9 y"} {:process 9, :type :invoke, :f :append, :key "0", :value "x 9 10 y"} {:process 0, :type :ok, :f :get, :key "9", :value "x 5 14 yx 6 18 yx 1 1 yx 0 7 y"} {:process 0, :type :invoke, :f :put, :key "1", :value "x 0 10 y"} {:process 4, :type :ok, :f :append, :key "5", :value "x 4 7 y"} {:process 4, :type :invoke, :f :append, :key "5", :value "x 4 8 y"} {:process 5, :type :ok, :f :get, :key "7", :value ""} {:process 7, :type :ok, :f :get, :key "1", :value ""} {:process 6, :type :ok, :f :put, :key "8", :value "x 6 19 y"} {:process 1, :type :ok, :f :append, :key "4", :value "x 1 3 y"} {:process 2, :type :ok, :f :append, :key "2", :value "x 2 14 y"} {:process 3, :type :ok, :f :append, :key "9", :value "x 3 7 y"} {:process 8, :type :ok, :f :append, :key "6", :value "x 8 10 y"} {:process 9, :type :ok, :f :append, :key "0", :value "x 9 10 y"} {:process 0, :type :ok, :f :put, :key "1", :value "x 0 10 y"} {:process 4, :type :ok, :f :append, :key "5", :value "x 4 8 y"} ================================================ FILE: courses/dss/linearizability/test_data/c10-ok.txt ================================================ {:process 9, :type :invoke, :f :append, :key "0", :value "x 9 0 y"} {:process 2, :type :invoke, :f :append, :key "1", :value "x 2 0 y"} {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 0 y"} {:process 1, :type :invoke, :f :get, :key "9", :value nil} {:process 5, :type :invoke, :f :append, :key "9", :value "x 5 0 y"} {:process 3, :type :invoke, :f :append, :key "9", :value "x 3 0 y"} {:process 4, :type :invoke, :f :append, :key "1", :value "x 4 0 y"} {:process 7, :type :invoke, :f :append, :key "5", :value "x 7 0 y"} {:process 6, :type :invoke, :f :append, :key "9", :value "x 6 0 y"} {:process 8, :type :invoke, :f :get, :key "8", :value nil} {:process 4, :type :ok, :f :append, :key "1", :value "x 4 0 y"} {:process 4, :type :invoke, :f :append, :key "1", :value "x 4 1 y"} {:process 9, :type :ok, :f :append, :key "0", :value "x 9 0 y"} {:process 9, :type :invoke, :f :append, :key "5", :value "x 9 1 y"} {:process 4, :type :ok, :f :append, :key "1", :value "x 4 1 y"} {:process 4, :type :invoke, :f :append, :key "4", :value "x 4 2 y"} {:process 9, :type :ok, :f :append, :key "5", :value "x 9 1 y"} {:process 9, :type :invoke, :f :append, :key "7", :value "x 9 2 y"} {:process 4, :type :ok, :f :append, :key "4", :value "x 4 2 y"} {:process 4, :type :invoke, :f :get, :key "3", :value nil} {:process 4, :type :ok, :f :get, :key "3", :value ""} {:process 4, :type :invoke, :f :append, :key "3", :value "x 4 3 y"} {:process 4, :type :ok, :f :append, :key "3", :value "x 4 3 y"} {:process 4, :type :invoke, :f :append, :key "9", :value "x 4 4 y"} {:process 4, :type :ok, :f :append, :key "9", :value "x 4 4 y"} {:process 4, :type :invoke, :f :append, :key "4", :value "x 4 5 y"} {:process 4, :type :ok, :f :append, :key "4", :value "x 4 5 y"} {:process 4, :type :invoke, :f :get, :key "5", :value nil} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 0 y"} {:process 0, :type :invoke, :f :get, :key "3", :value nil} {:process 4, :type :ok, :f :get, :key "5", :value "x 9 1 y"} {:process 4, :type :invoke, :f :append, :key "2", :value "x 4 6 y"} {:process 4, :type :ok, :f :append, :key "2", :value "x 4 6 y"} {:process 4, :type :invoke, :f :get, :key "9", :value nil} {:process 6, :type :ok, :f :append, :key "9", :value "x 6 0 y"} {:process 6, :type :invoke, :f :get, :key "6", :value nil} {:process 6, :type :ok, :f :get, :key "6", :value ""} {:process 6, :type :invoke, :f :append, :key "5", :value "x 6 1 y"} {:process 7, :type :ok, :f :append, :key "5", :value "x 7 0 y"} {:process 7, :type :invoke, :f :get, :key "0", :value nil} {:process 7, :type :ok, :f :get, :key "0", :value "x 9 0 yx 0 0 y"} {:process 7, :type :invoke, :f :append, :key "0", :value "x 7 1 y"} {:process 2, :type :ok, :f :append, :key "1", :value "x 2 0 y"} {:process 2, :type :invoke, :f :get, :key "5", :value nil} {:process 2, :type :ok, :f :get, :key "5", :value "x 9 1 yx 7 0 y"} {:process 2, :type :invoke, :f :append, :key "1", :value "x 2 1 y"} {:process 2, :type :ok, :f :append, :key "1", :value "x 2 1 y"} {:process 2, :type :invoke, :f :append, :key "5", :value "x 2 2 y"} {:process 3, :type :ok, :f :append, :key "9", :value "x 3 0 y"} {:process 3, :type :invoke, :f :append, :key "5", :value "x 3 1 y"} {:process 2, :type :ok, :f :append, :key "5", :value "x 2 2 y"} {:process 2, :type :invoke, :f :append, :key "9", :value "x 2 3 y"} {:process 3, :type :ok, :f :append, :key "5", :value "x 3 1 y"} {:process 3, :type :invoke, :f :append, :key "0", :value "x 3 2 y"} {:process 3, :type :ok, :f :append, :key "0", :value "x 3 2 y"} {:process 3, :type :invoke, :f :get, :key "9", :value nil} {:process 3, :type :ok, :f :get, :key "9", :value "x 4 4 yx 6 0 yx 3 0 y"} {:process 3, :type :invoke, :f :append, :key "5", :value "x 3 3 y"} {:process 8, :type :ok, :f :get, :key "8", :value ""} {:process 8, :type :invoke, :f :get, :key "1", :value nil} {:process 5, :type :ok, :f :append, :key "9", :value "x 5 0 y"} {:process 5, :type :invoke, :f :get, :key "8", :value nil} {:process 9, :type :ok, :f :append, :key "7", :value "x 9 2 y"} {:process 9, :type :invoke, :f :put, :key "6", :value "x 9 3 y"} {:process 4, :type :ok, :f :get, :key "9", :value "x 4 4 yx 6 0 yx 3 0 yx 5 0 y"} {:process 4, :type :invoke, :f :append, :key "4", :value "x 4 7 y"} {:process 1, :type :ok, :f :get, :key "9", :value "x 4 4 yx 6 0 yx 3 0 yx 5 0 y"} {:process 1, :type :invoke, :f :append, :key "1", :value "x 1 0 y"} {:process 6, :type :ok, :f :append, :key "5", :value "x 6 1 y"} {:process 6, :type :invoke, :f :get, :key "1", :value nil} {:process 4, :type :ok, :f :append, :key "4", :value "x 4 7 y"} {:process 4, :type :invoke, :f :append, :key "8", :value "x 4 8 y"} {:process 1, :type :ok, :f :append, :key "1", :value "x 1 0 y"} {:process 1, :type :invoke, :f :append, :key "2", :value "x 1 1 y"} {:process 7, :type :ok, :f :append, :key "0", :value "x 7 1 y"} {:process 7, :type :invoke, :f :append, :key "5", :value "x 7 2 y"} {:process 7, :type :ok, :f :append, :key "5", :value "x 7 2 y"} {:process 7, :type :invoke, :f :append, :key "9", :value "x 7 3 y"} {:process 1, :type :ok, :f :append, :key "2", :value "x 1 1 y"} {:process 1, :type :invoke, :f :put, :key "7", :value "x 1 2 y"} {:process 4, :type :ok, :f :append, :key "8", :value "x 4 8 y"} {:process 4, :type :invoke, :f :append, :key "5", :value "x 4 9 y"} {:process 7, :type :ok, :f :append, :key "9", :value "x 7 3 y"} {:process 7, :type :invoke, :f :get, :key "8", :value nil} {:process 1, :type :ok, :f :put, :key "7", :value "x 1 2 y"} {:process 1, :type :invoke, :f :append, :key "4", :value "x 1 3 y"} {:process 4, :type :ok, :f :append, :key "5", :value "x 4 9 y"} {:process 4, :type :invoke, :f :append, :key "8", :value "x 4 10 y"} {:process 1, :type :ok, :f :append, :key "4", :value "x 1 3 y"} {:process 1, :type :invoke, :f :get, :key "5", :value nil} {:process 7, :type :ok, :f :get, :key "8", :value "x 4 8 y"} {:process 7, :type :invoke, :f :put, :key "6", :value "x 7 4 y"} {:process 1, :type :ok, :f :get, :key "5", :value "x 9 1 yx 7 0 yx 3 1 yx 2 2 yx 6 1 yx 7 2 yx 4 9 y"} {:process 1, :type :invoke, :f :get, :key "4", :value nil} {:process 6, :type :ok, :f :get, :key "1", :value "x 4 0 yx 4 1 yx 2 0 yx 2 1 yx 1 0 y"} {:process 6, :type :invoke, :f :append, :key "2", :value "x 6 2 y"} {:process 6, :type :ok, :f :append, :key "2", :value "x 6 2 y"} {:process 6, :type :invoke, :f :get, :key "9", :value nil} {:process 6, :type :ok, :f :get, :key "9", :value "x 4 4 yx 6 0 yx 3 0 yx 5 0 yx 7 3 y"} {:process 6, :type :invoke, :f :get, :key "8", :value nil} {:process 4, :type :ok, :f :append, :key "8", :value "x 4 10 y"} {:process 4, :type :invoke, :f :get, :key "6", :value nil} {:process 1, :type :ok, :f :get, :key "4", :value "x 4 2 yx 4 5 yx 4 7 yx 1 3 y"} {:process 1, :type :invoke, :f :append, :key "4", :value "x 1 4 y"} {:process 0, :type :ok, :f :get, :key "3", :value "x 4 3 y"} {:process 0, :type :invoke, :f :append, :key "8", :value "x 0 1 y"} {:process 0, :type :ok, :f :append, :key "8", :value "x 0 1 y"} {:process 0, :type :invoke, :f :append, :key "2", :value "x 0 2 y"} {:process 8, :type :ok, :f :get, :key "1", :value "x 4 0 yx 4 1 yx 2 0 yx 2 1 yx 1 0 y"} {:process 8, :type :invoke, :f :get, :key "9", :value nil} {:process 0, :type :ok, :f :append, :key "2", :value "x 0 2 y"} {:process 0, :type :invoke, :f :get, :key "0", :value nil} {:process 8, :type :ok, :f :get, :key "9", :value "x 4 4 yx 6 0 yx 3 0 yx 5 0 yx 7 3 yx 2 3 y"} {:process 8, :type :invoke, :f :get, :key "7", :value nil} {:process 3, :type :ok, :f :append, :key "5", :value "x 3 3 y"} {:process 3, :type :invoke, :f :get, :key "4", :value nil} {:process 0, :type :ok, :f :get, :key "0", :value "x 9 0 yx 0 0 yx 3 2 yx 7 1 y"} {:process 0, :type :invoke, :f :append, :key "8", :value "x 0 3 y"} {:process 3, :type :ok, :f :get, :key "4", :value "x 4 2 yx 4 5 yx 4 7 yx 1 3 y"} {:process 3, :type :invoke, :f :get, :key "1", :value nil} {:process 0, :type :ok, :f :append, :key "8", :value "x 0 3 y"} {:process 0, :type :invoke, :f :get, :key "9", :value nil} {:process 0, :type :ok, :f :get, :key "9", :value "x 4 4 yx 6 0 yx 3 0 yx 5 0 yx 7 3 yx 2 3 y"} {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 4 y"} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 4 y"} {:process 0, :type :invoke, :f :get, :key "1", :value nil} {:process 6, :type :ok, :f :get, :key "8", :value "x 4 8 yx 4 10 yx 0 1 yx 0 3 y"} {:process 6, :type :invoke, :f :get, :key "9", :value nil} {:process 0, :type :ok, :f :get, :key "1", :value "x 4 0 yx 4 1 yx 2 0 yx 2 1 yx 1 0 y"} {:process 0, :type :invoke, :f :append, :key "5", :value "x 0 5 y"} {:process 3, :type :ok, :f :get, :key "1", :value "x 4 0 yx 4 1 yx 2 0 yx 2 1 yx 1 0 y"} {:process 3, :type :invoke, :f :append, :key "8", :value "x 3 4 y"} {:process 3, :type :ok, :f :append, :key "8", :value "x 3 4 y"} {:process 3, :type :invoke, :f :get, :key "9", :value nil} {:process 0, :type :ok, :f :append, :key "5", :value "x 0 5 y"} {:process 0, :type :invoke, :f :append, :key "7", :value "x 0 6 y"} {:process 7, :type :ok, :f :put, :key "6", :value "x 7 4 y"} {:process 7, :type :invoke, :f :append, :key "0", :value "x 7 5 y"} {:process 0, :type :ok, :f :append, :key "7", :value "x 0 6 y"} {:process 0, :type :invoke, :f :append, :key "3", :value "x 0 7 y"} {:process 7, :type :ok, :f :append, :key "0", :value "x 7 5 y"} {:process 7, :type :invoke, :f :append, :key "0", :value "x 7 6 y"} {:process 6, :type :ok, :f :get, :key "9", :value "x 4 4 yx 6 0 yx 3 0 yx 5 0 yx 7 3 yx 2 3 y"} {:process 6, :type :invoke, :f :append, :key "9", :value "x 6 3 y"} {:process 4, :type :ok, :f :get, :key "6", :value "x 7 4 y"} {:process 4, :type :invoke, :f :get, :key "1", :value nil} {:process 4, :type :ok, :f :get, :key "1", :value "x 4 0 yx 4 1 yx 2 0 yx 2 1 yx 1 0 y"} {:process 4, :type :invoke, :f :append, :key "6", :value "x 4 11 y"} {:process 0, :type :ok, :f :append, :key "3", :value "x 0 7 y"} {:process 7, :type :ok, :f :append, :key "0", :value "x 7 6 y"} {:process 4, :type :ok, :f :append, :key "6", :value "x 4 11 y"} {:process 0, :type :invoke, :f :get, :key "1", :value nil} {:process 7, :type :invoke, :f :get, :key "9", :value nil} {:process 4, :type :invoke, :f :append, :key "8", :value "x 4 12 y"} {:process 4, :type :ok, :f :append, :key "8", :value "x 4 12 y"} {:process 4, :type :invoke, :f :append, :key "0", :value "x 4 13 y"} {:process 7, :type :ok, :f :get, :key "9", :value "x 4 4 yx 6 0 yx 3 0 yx 5 0 yx 7 3 yx 2 3 y"} {:process 7, :type :invoke, :f :put, :key "4", :value "x 7 7 y"} {:process 7, :type :ok, :f :put, :key "4", :value "x 7 7 y"} {:process 7, :type :invoke, :f :get, :key "4", :value nil} {:process 4, :type :ok, :f :append, :key "0", :value "x 4 13 y"} {:process 4, :type :invoke, :f :get, :key "8", :value nil} {:process 4, :type :ok, :f :get, :key "8", :value "x 4 8 yx 4 10 yx 0 1 yx 0 3 yx 3 4 yx 4 12 y"} {:process 4, :type :invoke, :f :get, :key "8", :value nil} {:process 7, :type :ok, :f :get, :key "4", :value "x 7 7 y"} {:process 7, :type :invoke, :f :get, :key "0", :value nil} {:process 4, :type :ok, :f :get, :key "8", :value "x 4 8 yx 4 10 yx 0 1 yx 0 3 yx 3 4 yx 4 12 y"} {:process 4, :type :invoke, :f :append, :key "0", :value "x 4 14 y"} {:process 7, :type :ok, :f :get, :key "0", :value "x 9 0 yx 0 0 yx 3 2 yx 7 1 yx 0 4 yx 7 5 yx 7 6 yx 4 13 y"} {:process 7, :type :invoke, :f :get, :key "5", :value nil} {:process 4, :type :ok, :f :append, :key "0", :value "x 4 14 y"} {:process 4, :type :invoke, :f :get, :key "9", :value nil} {:process 5, :type :ok, :f :get, :key "8", :value "x 4 8 yx 4 10 yx 0 1 yx 0 3 yx 3 4 yx 4 12 y"} {:process 5, :type :invoke, :f :get, :key "5", :value nil} {:process 2, :type :ok, :f :append, :key "9", :value "x 2 3 y"} {:process 2, :type :invoke, :f :append, :key "0", :value "x 2 4 y"} {:process 7, :type :ok, :f :get, :key "5", :value "x 9 1 yx 7 0 yx 3 1 yx 2 2 yx 6 1 yx 7 2 yx 4 9 yx 3 3 yx 0 5 y"} {:process 7, :type :invoke, :f :append, :key "2", :value "x 7 8 y"} {:process 5, :type :ok, :f :get, :key "5", :value "x 9 1 yx 7 0 yx 3 1 yx 2 2 yx 6 1 yx 7 2 yx 4 9 yx 3 3 yx 0 5 y"} {:process 5, :type :invoke, :f :append, :key "4", :value "x 5 1 y"} {:process 4, :type :ok, :f :get, :key "9", :value "x 4 4 yx 6 0 yx 3 0 yx 5 0 yx 7 3 yx 2 3 y"} {:process 4, :type :invoke, :f :append, :key "1", :value "x 4 15 y"} {:process 7, :type :ok, :f :append, :key "2", :value "x 7 8 y"} {:process 7, :type :invoke, :f :append, :key "5", :value "x 7 9 y"} {:process 2, :type :ok, :f :append, :key "0", :value "x 2 4 y"} {:process 2, :type :invoke, :f :append, :key "5", :value "x 2 5 y"} {:process 4, :type :ok, :f :append, :key "1", :value "x 4 15 y"} {:process 4, :type :invoke, :f :append, :key "6", :value "x 4 16 y"} {:process 7, :type :ok, :f :append, :key "5", :value "x 7 9 y"} {:process 7, :type :invoke, :f :get, :key "8", :value nil} {:process 5, :type :ok, :f :append, :key "4", :value "x 5 1 y"} {:process 5, :type :invoke, :f :get, :key "2", :value nil} {:process 4, :type :ok, :f :append, :key "6", :value "x 4 16 y"} {:process 4, :type :invoke, :f :append, :key "6", :value "x 4 17 y"} {:process 2, :type :ok, :f :append, :key "5", :value "x 2 5 y"} {:process 2, :type :invoke, :f :append, :key "4", :value "x 2 6 y"} {:process 5, :type :ok, :f :get, :key "2", :value "x 4 6 yx 1 1 yx 6 2 yx 0 2 yx 7 8 y"} {:process 5, :type :invoke, :f :append, :key "7", :value "x 5 2 y"} {:process 7, :type :ok, :f :get, :key "8", :value "x 4 8 yx 4 10 yx 0 1 yx 0 3 yx 3 4 yx 4 12 y"} {:process 7, :type :invoke, :f :append, :key "7", :value "x 7 10 y"} {:process 5, :type :ok, :f :append, :key "7", :value "x 5 2 y"} {:process 5, :type :invoke, :f :append, :key "1", :value "x 5 3 y"} {:process 4, :type :ok, :f :append, :key "6", :value "x 4 17 y"} {:process 4, :type :invoke, :f :get, :key "3", :value nil} {:process 4, :type :ok, :f :get, :key "3", :value "x 4 3 yx 0 7 y"} {:process 4, :type :invoke, :f :append, :key "1", :value "x 4 18 y"} {:process 4, :type :ok, :f :append, :key "1", :value "x 4 18 y"} {:process 4, :type :invoke, :f :get, :key "2", :value nil} {:process 4, :type :ok, :f :get, :key "2", :value "x 4 6 yx 1 1 yx 6 2 yx 0 2 yx 7 8 y"} {:process 4, :type :invoke, :f :append, :key "3", :value "x 4 19 y"} {:process 4, :type :ok, :f :append, :key "3", :value "x 4 19 y"} {:process 4, :type :invoke, :f :append, :key "7", :value "x 4 20 y"} {:process 4, :type :ok, :f :append, :key "7", :value "x 4 20 y"} {:process 4, :type :invoke, :f :get, :key "8", :value nil} {:process 8, :type :ok, :f :get, :key "7", :value "x 1 2 yx 0 6 yx 5 2 yx 7 10 yx 4 20 y"} {:process 8, :type :invoke, :f :get, :key "2", :value nil} {:process 8, :type :ok, :f :get, :key "2", :value "x 4 6 yx 1 1 yx 6 2 yx 0 2 yx 7 8 y"} {:process 8, :type :invoke, :f :put, :key "3", :value "x 8 0 y"} {:process 8, :type :ok, :f :put, :key "3", :value "x 8 0 y"} {:process 8, :type :invoke, :f :append, :key "4", :value "x 8 1 y"} {:process 8, :type :ok, :f :append, :key "4", :value "x 8 1 y"} {:process 8, :type :invoke, :f :append, :key "9", :value "x 8 2 y"} {:process 8, :type :ok, :f :append, :key "9", :value "x 8 2 y"} {:process 8, :type :invoke, :f :append, :key "9", :value "x 8 3 y"} {:process 8, :type :ok, :f :append, :key "9", :value "x 8 3 y"} {:process 8, :type :invoke, :f :append, :key "0", :value "x 8 4 y"} {:process 6, :type :ok, :f :append, :key "9", :value "x 6 3 y"} {:process 6, :type :invoke, :f :get, :key "3", :value nil} {:process 1, :type :ok, :f :append, :key "4", :value "x 1 4 y"} {:process 1, :type :invoke, :f :append, :key "5", :value "x 1 5 y"} {:process 9, :type :ok, :f :put, :key "6", :value "x 9 3 y"} {:process 9, :type :invoke, :f :get, :key "4", :value nil} {:process 2, :type :ok, :f :append, :key "4", :value "x 2 6 y"} {:process 2, :type :invoke, :f :append, :key "5", :value "x 2 7 y"} {:process 9, :type :ok, :f :get, :key "4", :value "x 7 7 yx 5 1 yx 1 4 yx 2 6 yx 8 1 y"} {:process 9, :type :invoke, :f :get, :key "4", :value nil} {:process 2, :type :ok, :f :append, :key "5", :value "x 2 7 y"} {:process 2, :type :invoke, :f :append, :key "6", :value "x 2 8 y"} {:process 5, :type :ok, :f :append, :key "1", :value "x 5 3 y"} {:process 5, :type :invoke, :f :append, :key "3", :value "x 5 4 y"} {:process 2, :type :ok, :f :append, :key "6", :value "x 2 8 y"} {:process 2, :type :invoke, :f :append, :key "5", :value "x 2 9 y"} {:process 5, :type :ok, :f :append, :key "3", :value "x 5 4 y"} {:process 5, :type :invoke, :f :get, :key "7", :value nil} {:process 7, :type :ok, :f :append, :key "7", :value "x 7 10 y"} {:process 7, :type :invoke, :f :get, :key "5", :value nil} {:process 7, :type :ok, :f :get, :key "5", :value "x 9 1 yx 7 0 yx 3 1 yx 2 2 yx 6 1 yx 7 2 yx 4 9 yx 3 3 yx 0 5 yx 7 9 yx 2 5 yx 1 5 yx 2 7 y"} {:process 7, :type :invoke, :f :put, :key "7", :value "x 7 11 y"} {:process 5, :type :ok, :f :get, :key "7", :value "x 1 2 yx 0 6 yx 5 2 yx 7 10 yx 4 20 y"} {:process 5, :type :invoke, :f :append, :key "0", :value "x 5 5 y"} {:process 5, :type :ok, :f :append, :key "0", :value "x 5 5 y"} {:process 5, :type :invoke, :f :get, :key "1", :value nil} {:process 7, :type :ok, :f :put, :key "7", :value "x 7 11 y"} {:process 7, :type :invoke, :f :append, :key "6", :value "x 7 12 y"} {:process 5, :type :ok, :f :get, :key "1", :value "x 4 0 yx 4 1 yx 2 0 yx 2 1 yx 1 0 yx 4 15 yx 4 18 yx 5 3 y"} {:process 5, :type :invoke, :f :append, :key "5", :value "x 5 6 y"} {:process 5, :type :ok, :f :append, :key "5", :value "x 5 6 y"} {:process 5, :type :invoke, :f :append, :key "0", :value "x 5 7 y"} {:process 5, :type :ok, :f :append, :key "0", :value "x 5 7 y"} {:process 5, :type :invoke, :f :get, :key "0", :value nil} {:process 5, :type :ok, :f :get, :key "0", :value "x 9 0 yx 0 0 yx 3 2 yx 7 1 yx 0 4 yx 7 5 yx 7 6 yx 4 13 yx 4 14 yx 2 4 yx 8 4 yx 5 5 yx 5 7 y"} {:process 5, :type :invoke, :f :append, :key "3", :value "x 5 8 y"} {:process 5, :type :ok, :f :append, :key "3", :value "x 5 8 y"} {:process 5, :type :invoke, :f :get, :key "3", :value nil} {:process 5, :type :ok, :f :get, :key "3", :value "x 8 0 yx 5 4 yx 5 8 y"} {:process 5, :type :invoke, :f :append, :key "8", :value "x 5 9 y"} {:process 5, :type :ok, :f :append, :key "8", :value "x 5 9 y"} {:process 5, :type :invoke, :f :append, :key "4", :value "x 5 10 y"} {:process 5, :type :ok, :f :append, :key "4", :value "x 5 10 y"} {:process 5, :type :invoke, :f :put, :key "5", :value "x 5 11 y"} {:process 4, :type :ok, :f :get, :key "8", :value "x 4 8 yx 4 10 yx 0 1 yx 0 3 yx 3 4 yx 4 12 yx 5 9 y"} {:process 4, :type :invoke, :f :put, :key "5", :value "x 4 21 y"} {:process 5, :type :ok, :f :put, :key "5", :value "x 5 11 y"} {:process 5, :type :invoke, :f :get, :key "4", :value nil} {:process 5, :type :ok, :f :get, :key "4", :value "x 7 7 yx 5 1 yx 1 4 yx 2 6 yx 8 1 yx 5 10 y"} {:process 5, :type :invoke, :f :get, :key "7", :value nil} {:process 5, :type :ok, :f :get, :key "7", :value "x 7 11 y"} {:process 5, :type :invoke, :f :get, :key "4", :value nil} {:process 5, :type :ok, :f :get, :key "4", :value "x 7 7 yx 5 1 yx 1 4 yx 2 6 yx 8 1 yx 5 10 y"} {:process 5, :type :invoke, :f :append, :key "0", :value "x 5 12 y"} {:process 5, :type :ok, :f :append, :key "0", :value "x 5 12 y"} {:process 5, :type :invoke, :f :get, :key "4", :value nil} {:process 5, :type :ok, :f :get, :key "4", :value "x 7 7 yx 5 1 yx 1 4 yx 2 6 yx 8 1 yx 5 10 y"} {:process 5, :type :invoke, :f :append, :key "5", :value "x 5 13 y"} {:process 4, :type :ok, :f :put, :key "5", :value "x 4 21 y"} {:process 7, :type :ok, :f :append, :key "6", :value "x 7 12 y"} {:process 6, :type :ok, :f :get, :key "3", :value "x 8 0 yx 5 4 yx 5 8 y"} {:process 5, :type :ok, :f :append, :key "5", :value "x 5 13 y"} {:process 3, :type :ok, :f :get, :key "9", :value "x 4 4 yx 6 0 yx 3 0 yx 5 0 yx 7 3 yx 2 3 yx 8 2 yx 8 3 yx 6 3 y"} {:process 0, :type :ok, :f :get, :key "1", :value "x 4 0 yx 4 1 yx 2 0 yx 2 1 yx 1 0 yx 4 15 yx 4 18 yx 5 3 y"} {:process 8, :type :ok, :f :append, :key "0", :value "x 8 4 y"} {:process 2, :type :ok, :f :append, :key "5", :value "x 2 9 y"} {:process 9, :type :ok, :f :get, :key "4", :value "x 7 7 yx 5 1 yx 1 4 yx 2 6 yx 8 1 yx 5 10 y"} {:process 1, :type :ok, :f :append, :key "5", :value "x 1 5 y"} {:process 9, :type :invoke, :f :get, :key "8", :value nil} {:process 3, :type :invoke, :f :append, :key "4", :value "x 3 0 y"} {:process 4, :type :invoke, :f :get, :key "2", :value nil} {:process 2, :type :invoke, :f :append, :key "4", :value "x 2 0 y"} {:process 5, :type :invoke, :f :append, :key "8", :value "x 5 0 y"} {:process 6, :type :invoke, :f :get, :key "6", :value nil} {:process 0, :type :invoke, :f :put, :key "1", :value "x 0 0 y"} {:process 7, :type :invoke, :f :append, :key "4", :value "x 7 0 y"} {:process 8, :type :invoke, :f :append, :key "8", :value "x 8 0 y"} {:process 1, :type :invoke, :f :append, :key "1", :value "x 1 0 y"} {:process 8, :type :ok, :f :append, :key "8", :value "x 8 0 y"} {:process 8, :type :invoke, :f :get, :key "6", :value nil} {:process 8, :type :ok, :f :get, :key "6", :value "x 7 4 yx 4 11 yx 4 16 yx 4 17 yx 2 8 yx 7 12 y"} {:process 8, :type :invoke, :f :get, :key "5", :value nil} {:process 8, :type :ok, :f :get, :key "5", :value "x 5 11 yx 5 13 yx 2 9 y"} {:process 8, :type :invoke, :f :append, :key "2", :value "x 8 1 y"} {:process 8, :type :ok, :f :append, :key "2", :value "x 8 1 y"} {:process 8, :type :invoke, :f :append, :key "1", :value "x 8 2 y"} {:process 5, :type :ok, :f :append, :key "8", :value "x 5 0 y"} {:process 5, :type :invoke, :f :append, :key "8", :value "x 5 1 y"} {:process 5, :type :ok, :f :append, :key "8", :value "x 5 1 y"} {:process 5, :type :invoke, :f :append, :key "8", :value "x 5 2 y"} {:process 8, :type :ok, :f :append, :key "1", :value "x 8 2 y"} {:process 8, :type :invoke, :f :append, :key "3", :value "x 8 3 y"} {:process 8, :type :ok, :f :append, :key "3", :value "x 8 3 y"} {:process 8, :type :invoke, :f :append, :key "2", :value "x 8 4 y"} {:process 8, :type :ok, :f :append, :key "2", :value "x 8 4 y"} {:process 8, :type :invoke, :f :get, :key "4", :value nil} {:process 8, :type :ok, :f :get, :key "4", :value "x 7 7 yx 5 1 yx 1 4 yx 2 6 yx 8 1 yx 5 10 y"} {:process 8, :type :invoke, :f :append, :key "5", :value "x 8 5 y"} {:process 9, :type :ok, :f :get, :key "8", :value "x 4 8 yx 4 10 yx 0 1 yx 0 3 yx 3 4 yx 4 12 yx 5 9 yx 8 0 yx 5 0 yx 5 1 y"} {:process 9, :type :invoke, :f :append, :key "7", :value "x 9 0 y"} {:process 7, :type :ok, :f :append, :key "4", :value "x 7 0 y"} {:process 7, :type :invoke, :f :get, :key "5", :value nil} {:process 9, :type :ok, :f :append, :key "7", :value "x 9 0 y"} {:process 9, :type :invoke, :f :append, :key "3", :value "x 9 1 y"} {:process 8, :type :ok, :f :append, :key "5", :value "x 8 5 y"} {:process 8, :type :invoke, :f :append, :key "7", :value "x 8 6 y"} {:process 8, :type :ok, :f :append, :key "7", :value "x 8 6 y"} {:process 8, :type :invoke, :f :get, :key "8", :value nil} {:process 7, :type :ok, :f :get, :key "5", :value "x 5 11 yx 5 13 yx 2 9 yx 8 5 y"} {:process 7, :type :invoke, :f :append, :key "3", :value "x 7 1 y"} {:process 9, :type :ok, :f :append, :key "3", :value "x 9 1 y"} {:process 9, :type :invoke, :f :get, :key "5", :value nil} {:process 8, :type :ok, :f :get, :key "8", :value "x 4 8 yx 4 10 yx 0 1 yx 0 3 yx 3 4 yx 4 12 yx 5 9 yx 8 0 yx 5 0 yx 5 1 y"} {:process 8, :type :invoke, :f :append, :key "3", :value "x 8 7 y"} {:process 7, :type :ok, :f :append, :key "3", :value "x 7 1 y"} {:process 7, :type :invoke, :f :get, :key "8", :value nil} {:process 9, :type :ok, :f :get, :key "5", :value "x 5 11 yx 5 13 yx 2 9 yx 8 5 y"} {:process 9, :type :invoke, :f :get, :key "1", :value nil} {:process 7, :type :ok, :f :get, :key "8", :value "x 4 8 yx 4 10 yx 0 1 yx 0 3 yx 3 4 yx 4 12 yx 5 9 yx 8 0 yx 5 0 yx 5 1 y"} {:process 7, :type :invoke, :f :get, :key "2", :value nil} {:process 8, :type :ok, :f :append, :key "3", :value "x 8 7 y"} {:process 8, :type :invoke, :f :get, :key "7", :value nil} {:process 9, :type :ok, :f :get, :key "1", :value "x 4 0 yx 4 1 yx 2 0 yx 2 1 yx 1 0 yx 4 15 yx 4 18 yx 5 3 yx 8 2 y"} {:process 9, :type :invoke, :f :get, :key "7", :value nil} {:process 7, :type :ok, :f :get, :key "2", :value "x 4 6 yx 1 1 yx 6 2 yx 0 2 yx 7 8 yx 8 1 yx 8 4 y"} {:process 7, :type :invoke, :f :append, :key "9", :value "x 7 2 y"} {:process 7, :type :ok, :f :append, :key "9", :value "x 7 2 y"} {:process 7, :type :invoke, :f :append, :key "9", :value "x 7 3 y"} {:process 1, :type :ok, :f :append, :key "1", :value "x 1 0 y"} {:process 1, :type :invoke, :f :append, :key "1", :value "x 1 1 y"} {:process 8, :type :ok, :f :get, :key "7", :value "x 7 11 yx 9 0 yx 8 6 y"} {:process 8, :type :invoke, :f :get, :key "1", :value nil} {:process 1, :type :ok, :f :append, :key "1", :value "x 1 1 y"} {:process 1, :type :invoke, :f :get, :key "6", :value nil} {:process 8, :type :ok, :f :get, :key "1", :value "x 4 0 yx 4 1 yx 2 0 yx 2 1 yx 1 0 yx 4 15 yx 4 18 yx 5 3 yx 8 2 yx 1 0 yx 1 1 y"} {:process 8, :type :invoke, :f :put, :key "8", :value "x 8 8 y"} {:process 1, :type :ok, :f :get, :key "6", :value "x 7 4 yx 4 11 yx 4 16 yx 4 17 yx 2 8 yx 7 12 y"} {:process 1, :type :invoke, :f :append, :key "7", :value "x 1 2 y"} {:process 1, :type :ok, :f :append, :key "7", :value "x 1 2 y"} {:process 1, :type :invoke, :f :append, :key "7", :value "x 1 3 y"} {:process 3, :type :ok, :f :append, :key "4", :value "x 3 0 y"} {:process 3, :type :invoke, :f :get, :key "5", :value nil} {:process 1, :type :ok, :f :append, :key "7", :value "x 1 3 y"} {:process 1, :type :invoke, :f :append, :key "7", :value "x 1 4 y"} {:process 1, :type :ok, :f :append, :key "7", :value "x 1 4 y"} {:process 1, :type :invoke, :f :append, :key "2", :value "x 1 5 y"} {:process 1, :type :ok, :f :append, :key "2", :value "x 1 5 y"} {:process 1, :type :invoke, :f :get, :key "4", :value nil} {:process 1, :type :ok, :f :get, :key "4", :value "x 7 7 yx 5 1 yx 1 4 yx 2 6 yx 8 1 yx 5 10 yx 7 0 yx 3 0 y"} {:process 1, :type :invoke, :f :get, :key "5", :value nil} {:process 0, :type :ok, :f :put, :key "1", :value "x 0 0 y"} {:process 0, :type :invoke, :f :get, :key "9", :value nil} {:process 4, :type :ok, :f :get, :key "2", :value "x 4 6 yx 1 1 yx 6 2 yx 0 2 yx 7 8 yx 8 1 yx 8 4 yx 1 5 y"} {:process 4, :type :invoke, :f :append, :key "9", :value "x 4 0 y"} {:process 2, :type :ok, :f :append, :key "4", :value "x 2 0 y"} {:process 2, :type :invoke, :f :get, :key "3", :value nil} {:process 0, :type :ok, :f :get, :key "9", :value "x 4 4 yx 6 0 yx 3 0 yx 5 0 yx 7 3 yx 2 3 yx 8 2 yx 8 3 yx 6 3 yx 7 2 yx 7 3 yx 4 0 y"} {:process 0, :type :invoke, :f :append, :key "1", :value "x 0 1 y"} {:process 0, :type :ok, :f :append, :key "1", :value "x 0 1 y"} {:process 0, :type :invoke, :f :append, :key "8", :value "x 0 2 y"} {:process 0, :type :ok, :f :append, :key "8", :value "x 0 2 y"} {:process 0, :type :invoke, :f :get, :key "2", :value nil} {:process 0, :type :ok, :f :get, :key "2", :value "x 4 6 yx 1 1 yx 6 2 yx 0 2 yx 7 8 yx 8 1 yx 8 4 yx 1 5 y"} {:process 0, :type :invoke, :f :append, :key "1", :value "x 0 3 y"} {:process 0, :type :ok, :f :append, :key "1", :value "x 0 3 y"} {:process 0, :type :invoke, :f :append, :key "8", :value "x 0 4 y"} {:process 0, :type :ok, :f :append, :key "8", :value "x 0 4 y"} {:process 0, :type :invoke, :f :get, :key "8", :value nil} {:process 0, :type :ok, :f :get, :key "8", :value "x 8 8 yx 0 2 yx 0 4 y"} {:process 0, :type :invoke, :f :append, :key "7", :value "x 0 5 y"} {:process 0, :type :ok, :f :append, :key "7", :value "x 0 5 y"} {:process 0, :type :invoke, :f :get, :key "3", :value nil} {:process 0, :type :ok, :f :get, :key "3", :value "x 8 0 yx 5 4 yx 5 8 yx 8 3 yx 9 1 yx 7 1 yx 8 7 y"} {:process 0, :type :invoke, :f :append, :key "9", :value "x 0 6 y"} {:process 0, :type :ok, :f :append, :key "9", :value "x 0 6 y"} {:process 0, :type :invoke, :f :append, :key "8", :value "x 0 7 y"} {:process 7, :type :ok, :f :append, :key "9", :value "x 7 3 y"} {:process 7, :type :invoke, :f :append, :key "1", :value "x 7 4 y"} {:process 5, :type :ok, :f :append, :key "8", :value "x 5 2 y"} {:process 5, :type :invoke, :f :append, :key "9", :value "x 5 3 y"} {:process 5, :type :ok, :f :append, :key "9", :value "x 5 3 y"} {:process 5, :type :invoke, :f :get, :key "9", :value nil} {:process 7, :type :ok, :f :append, :key "1", :value "x 7 4 y"} {:process 7, :type :invoke, :f :append, :key "4", :value "x 7 5 y"} {:process 8, :type :ok, :f :put, :key "8", :value "x 8 8 y"} {:process 8, :type :invoke, :f :append, :key "0", :value "x 8 9 y"} {:process 5, :type :ok, :f :get, :key "9", :value "x 4 4 yx 6 0 yx 3 0 yx 5 0 yx 7 3 yx 2 3 yx 8 2 yx 8 3 yx 6 3 yx 7 2 yx 7 3 yx 4 0 yx 0 6 yx 5 3 y"} {:process 5, :type :invoke, :f :append, :key "2", :value "x 5 4 y"} {:process 8, :type :ok, :f :append, :key "0", :value "x 8 9 y"} {:process 8, :type :invoke, :f :get, :key "6", :value nil} {:process 7, :type :ok, :f :append, :key "4", :value "x 7 5 y"} {:process 7, :type :invoke, :f :get, :key "4", :value nil} {:process 8, :type :ok, :f :get, :key "6", :value "x 7 4 yx 4 11 yx 4 16 yx 4 17 yx 2 8 yx 7 12 y"} {:process 8, :type :invoke, :f :append, :key "7", :value "x 8 10 y"} {:process 5, :type :ok, :f :append, :key "2", :value "x 5 4 y"} {:process 5, :type :invoke, :f :put, :key "2", :value "x 5 5 y"} {:process 3, :type :ok, :f :get, :key "5", :value "x 5 11 yx 5 13 yx 2 9 yx 8 5 y"} {:process 3, :type :invoke, :f :append, :key "8", :value "x 3 1 y"} {:process 8, :type :ok, :f :append, :key "7", :value "x 8 10 y"} {:process 8, :type :invoke, :f :get, :key "3", :value nil} {:process 3, :type :ok, :f :append, :key "8", :value "x 3 1 y"} {:process 3, :type :invoke, :f :append, :key "3", :value "x 3 2 y"} {:process 5, :type :ok, :f :put, :key "2", :value "x 5 5 y"} {:process 5, :type :invoke, :f :append, :key "6", :value "x 5 6 y"} {:process 8, :type :ok, :f :get, :key "3", :value "x 8 0 yx 5 4 yx 5 8 yx 8 3 yx 9 1 yx 7 1 yx 8 7 y"} {:process 8, :type :invoke, :f :append, :key "4", :value "x 8 11 y"} {:process 8, :type :ok, :f :append, :key "4", :value "x 8 11 y"} {:process 8, :type :invoke, :f :append, :key "0", :value "x 8 12 y"} {:process 5, :type :ok, :f :append, :key "6", :value "x 5 6 y"} {:process 5, :type :invoke, :f :append, :key "3", :value "x 5 7 y"} {:process 2, :type :ok, :f :get, :key "3", :value "x 8 0 yx 5 4 yx 5 8 yx 8 3 yx 9 1 yx 7 1 yx 8 7 yx 3 2 y"} {:process 2, :type :invoke, :f :append, :key "7", :value "x 2 1 y"} {:process 3, :type :ok, :f :append, :key "3", :value "x 3 2 y"} {:process 3, :type :invoke, :f :get, :key "7", :value nil} {:process 4, :type :ok, :f :append, :key "9", :value "x 4 0 y"} {:process 4, :type :invoke, :f :get, :key "9", :value nil} {:process 8, :type :ok, :f :append, :key "0", :value "x 8 12 y"} {:process 8, :type :invoke, :f :get, :key "7", :value nil} {:process 4, :type :ok, :f :get, :key "9", :value "x 4 4 yx 6 0 yx 3 0 yx 5 0 yx 7 3 yx 2 3 yx 8 2 yx 8 3 yx 6 3 yx 7 2 yx 7 3 yx 4 0 yx 0 6 yx 5 3 y"} {:process 4, :type :invoke, :f :get, :key "6", :value nil} {:process 8, :type :ok, :f :get, :key "7", :value "x 7 11 yx 9 0 yx 8 6 yx 1 2 yx 1 3 yx 1 4 yx 0 5 yx 8 10 yx 2 1 y"} {:process 8, :type :invoke, :f :append, :key "2", :value "x 8 13 y"} {:process 0, :type :ok, :f :append, :key "8", :value "x 0 7 y"} {:process 0, :type :invoke, :f :get, :key "8", :value nil} {:process 0, :type :ok, :f :get, :key "8", :value "x 8 8 yx 0 2 yx 0 4 yx 0 7 yx 5 2 yx 3 1 y"} {:process 0, :type :invoke, :f :append, :key "4", :value "x 0 8 y"} {:process 0, :type :ok, :f :append, :key "4", :value "x 0 8 y"} {:process 0, :type :invoke, :f :get, :key "4", :value nil} {:process 0, :type :ok, :f :get, :key "4", :value "x 7 7 yx 5 1 yx 1 4 yx 2 6 yx 8 1 yx 5 10 yx 7 0 yx 3 0 yx 2 0 yx 7 5 yx 8 11 yx 0 8 y"} {:process 0, :type :invoke, :f :append, :key "6", :value "x 0 9 y"} {:process 7, :type :ok, :f :get, :key "4", :value "x 7 7 yx 5 1 yx 1 4 yx 2 6 yx 8 1 yx 5 10 yx 7 0 yx 3 0 yx 2 0 yx 7 5 yx 8 11 yx 0 8 y"} {:process 7, :type :invoke, :f :append, :key "6", :value "x 7 6 y"} {:process 7, :type :ok, :f :append, :key "6", :value "x 7 6 y"} {:process 7, :type :invoke, :f :append, :key "7", :value "x 7 7 y"} {:process 1, :type :ok, :f :get, :key "5", :value "x 5 11 yx 5 13 yx 2 9 yx 8 5 y"} {:process 1, :type :invoke, :f :append, :key "1", :value "x 1 6 y"} {:process 4, :type :ok, :f :get, :key "6", :value "x 7 4 yx 4 11 yx 4 16 yx 4 17 yx 2 8 yx 7 12 yx 5 6 yx 0 9 yx 7 6 y"} {:process 4, :type :invoke, :f :get, :key "5", :value nil} {:process 3, :type :ok, :f :get, :key "7", :value "x 7 11 yx 9 0 yx 8 6 yx 1 2 yx 1 3 yx 1 4 yx 0 5 yx 8 10 yx 2 1 y"} {:process 3, :type :invoke, :f :append, :key "0", :value "x 3 3 y"} {:process 2, :type :ok, :f :append, :key "7", :value "x 2 1 y"} {:process 2, :type :invoke, :f :put, :key "5", :value "x 2 2 y"} {:process 1, :type :ok, :f :append, :key "1", :value "x 1 6 y"} {:process 1, :type :invoke, :f :get, :key "3", :value nil} {:process 5, :type :ok, :f :append, :key "3", :value "x 5 7 y"} {:process 5, :type :invoke, :f :append, :key "3", :value "x 5 8 y"} {:process 3, :type :ok, :f :append, :key "0", :value "x 3 3 y"} {:process 3, :type :invoke, :f :get, :key "3", :value nil} {:process 1, :type :ok, :f :get, :key "3", :value "x 8 0 yx 5 4 yx 5 8 yx 8 3 yx 9 1 yx 7 1 yx 8 7 yx 3 2 yx 5 7 y"} {:process 1, :type :invoke, :f :get, :key "3", :value nil} {:process 8, :type :ok, :f :append, :key "2", :value "x 8 13 y"} {:process 8, :type :invoke, :f :get, :key "1", :value nil} {:process 5, :type :ok, :f :append, :key "3", :value "x 5 8 y"} {:process 5, :type :invoke, :f :append, :key "4", :value "x 5 9 y"} {:process 8, :type :ok, :f :get, :key "1", :value "x 0 0 yx 0 1 yx 0 3 yx 7 4 yx 1 6 y"} {:process 8, :type :invoke, :f :get, :key "1", :value nil} {:process 1, :type :ok, :f :get, :key "3", :value "x 8 0 yx 5 4 yx 5 8 yx 8 3 yx 9 1 yx 7 1 yx 8 7 yx 3 2 yx 5 7 yx 5 8 y"} {:process 1, :type :invoke, :f :append, :key "1", :value "x 1 7 y"} {:process 3, :type :ok, :f :get, :key "3", :value "x 8 0 yx 5 4 yx 5 8 yx 8 3 yx 9 1 yx 7 1 yx 8 7 yx 3 2 yx 5 7 yx 5 8 y"} {:process 3, :type :invoke, :f :append, :key "7", :value "x 3 4 y"} {:process 5, :type :ok, :f :append, :key "4", :value "x 5 9 y"} {:process 5, :type :invoke, :f :append, :key "4", :value "x 5 10 y"} {:process 1, :type :ok, :f :append, :key "1", :value "x 1 7 y"} {:process 8, :type :ok, :f :get, :key "1", :value "x 0 0 yx 0 1 yx 0 3 yx 7 4 yx 1 6 yx 1 7 y"} {:process 8, :type :invoke, :f :get, :key "6", :value nil} {:process 1, :type :invoke, :f :get, :key "7", :value nil} {:process 3, :type :ok, :f :append, :key "7", :value "x 3 4 y"} {:process 3, :type :invoke, :f :get, :key "9", :value nil} {:process 8, :type :ok, :f :get, :key "6", :value "x 7 4 yx 4 11 yx 4 16 yx 4 17 yx 2 8 yx 7 12 yx 5 6 yx 0 9 yx 7 6 y"} {:process 8, :type :invoke, :f :get, :key "3", :value nil} {:process 5, :type :ok, :f :append, :key "4", :value "x 5 10 y"} {:process 3, :type :ok, :f :get, :key "9", :value "x 4 4 yx 6 0 yx 3 0 yx 5 0 yx 7 3 yx 2 3 yx 8 2 yx 8 3 yx 6 3 yx 7 2 yx 7 3 yx 4 0 yx 0 6 yx 5 3 y"} {:process 5, :type :invoke, :f :append, :key "6", :value "x 5 11 y"} {:process 3, :type :invoke, :f :get, :key "1", :value nil} {:process 8, :type :ok, :f :get, :key "3", :value "x 8 0 yx 5 4 yx 5 8 yx 8 3 yx 9 1 yx 7 1 yx 8 7 yx 3 2 yx 5 7 yx 5 8 y"} {:process 8, :type :invoke, :f :get, :key "4", :value nil} {:process 1, :type :ok, :f :get, :key "7", :value "x 7 11 yx 9 0 yx 8 6 yx 1 2 yx 1 3 yx 1 4 yx 0 5 yx 8 10 yx 2 1 yx 3 4 y"} {:process 1, :type :invoke, :f :get, :key "1", :value nil} {:process 3, :type :ok, :f :get, :key "1", :value "x 0 0 yx 0 1 yx 0 3 yx 7 4 yx 1 6 yx 1 7 y"} {:process 3, :type :invoke, :f :get, :key "3", :value nil} {:process 1, :type :ok, :f :get, :key "1", :value "x 0 0 yx 0 1 yx 0 3 yx 7 4 yx 1 6 yx 1 7 y"} {:process 1, :type :invoke, :f :get, :key "2", :value nil} {:process 5, :type :ok, :f :append, :key "6", :value "x 5 11 y"} {:process 5, :type :invoke, :f :append, :key "3", :value "x 5 12 y"} {:process 8, :type :ok, :f :get, :key "4", :value "x 7 7 yx 5 1 yx 1 4 yx 2 6 yx 8 1 yx 5 10 yx 7 0 yx 3 0 yx 2 0 yx 7 5 yx 8 11 yx 0 8 yx 5 9 yx 5 10 y"} {:process 8, :type :invoke, :f :get, :key "1", :value nil} {:process 6, :type :ok, :f :get, :key "6", :value "x 7 4 yx 4 11 yx 4 16 yx 4 17 yx 2 8 yx 7 12 yx 5 6 yx 0 9 yx 7 6 yx 5 11 y"} {:process 6, :type :invoke, :f :get, :key "9", :value nil} {:process 3, :type :ok, :f :get, :key "3", :value "x 8 0 yx 5 4 yx 5 8 yx 8 3 yx 9 1 yx 7 1 yx 8 7 yx 3 2 yx 5 7 yx 5 8 y"} {:process 3, :type :invoke, :f :append, :key "1", :value "x 3 5 y"} {:process 5, :type :ok, :f :append, :key "3", :value "x 5 12 y"} {:process 5, :type :invoke, :f :put, :key "4", :value "x 5 13 y"} {:process 1, :type :ok, :f :get, :key "2", :value "x 5 5 yx 8 13 y"} {:process 1, :type :invoke, :f :append, :key "3", :value "x 1 8 y"} {:process 8, :type :ok, :f :get, :key "1", :value "x 0 0 yx 0 1 yx 0 3 yx 7 4 yx 1 6 yx 1 7 y"} {:process 8, :type :invoke, :f :get, :key "0", :value nil} {:process 5, :type :ok, :f :put, :key "4", :value "x 5 13 y"} {:process 5, :type :invoke, :f :get, :key "8", :value nil} {:process 6, :type :ok, :f :get, :key "9", :value "x 4 4 yx 6 0 yx 3 0 yx 5 0 yx 7 3 yx 2 3 yx 8 2 yx 8 3 yx 6 3 yx 7 2 yx 7 3 yx 4 0 yx 0 6 yx 5 3 y"} {:process 6, :type :invoke, :f :append, :key "0", :value "x 6 0 y"} {:process 1, :type :ok, :f :append, :key "3", :value "x 1 8 y"} {:process 1, :type :invoke, :f :append, :key "0", :value "x 1 9 y"} {:process 5, :type :ok, :f :get, :key "8", :value "x 8 8 yx 0 2 yx 0 4 yx 0 7 yx 5 2 yx 3 1 y"} {:process 5, :type :invoke, :f :get, :key "3", :value nil} {:process 6, :type :ok, :f :append, :key "0", :value "x 6 0 y"} {:process 6, :type :invoke, :f :append, :key "2", :value "x 6 1 y"} {:process 5, :type :ok, :f :get, :key "3", :value "x 8 0 yx 5 4 yx 5 8 yx 8 3 yx 9 1 yx 7 1 yx 8 7 yx 3 2 yx 5 7 yx 5 8 yx 5 12 yx 1 8 y"} {:process 5, :type :invoke, :f :append, :key "4", :value "x 5 14 y"} {:process 5, :type :ok, :f :append, :key "4", :value "x 5 14 y"} {:process 5, :type :invoke, :f :append, :key "2", :value "x 5 15 y"} {:process 1, :type :ok, :f :append, :key "0", :value "x 1 9 y"} {:process 1, :type :invoke, :f :append, :key "9", :value "x 1 10 y"} {:process 6, :type :ok, :f :append, :key "2", :value "x 6 1 y"} {:process 6, :type :invoke, :f :get, :key "2", :value nil} {:process 1, :type :ok, :f :append, :key "9", :value "x 1 10 y"} {:process 1, :type :invoke, :f :get, :key "8", :value nil} {:process 5, :type :ok, :f :append, :key "2", :value "x 5 15 y"} {:process 5, :type :invoke, :f :append, :key "9", :value "x 5 16 y"} {:process 1, :type :ok, :f :get, :key "8", :value "x 8 8 yx 0 2 yx 0 4 yx 0 7 yx 5 2 yx 3 1 y"} {:process 1, :type :invoke, :f :get, :key "9", :value nil} {:process 1, :type :ok, :f :get, :key "9", :value "x 4 4 yx 6 0 yx 3 0 yx 5 0 yx 7 3 yx 2 3 yx 8 2 yx 8 3 yx 6 3 yx 7 2 yx 7 3 yx 4 0 yx 0 6 yx 5 3 yx 1 10 y"} {:process 1, :type :invoke, :f :get, :key "4", :value nil} {:process 6, :type :ok, :f :get, :key "2", :value "x 5 5 yx 8 13 yx 6 1 yx 5 15 y"} {:process 6, :type :invoke, :f :get, :key "6", :value nil} {:process 5, :type :ok, :f :append, :key "9", :value "x 5 16 y"} {:process 5, :type :invoke, :f :append, :key "8", :value "x 5 17 y"} {:process 6, :type :ok, :f :get, :key "6", :value "x 7 4 yx 4 11 yx 4 16 yx 4 17 yx 2 8 yx 7 12 yx 5 6 yx 0 9 yx 7 6 yx 5 11 y"} {:process 6, :type :invoke, :f :append, :key "0", :value "x 6 2 y"} {:process 5, :type :ok, :f :append, :key "8", :value "x 5 17 y"} {:process 5, :type :invoke, :f :get, :key "0", :value nil} {:process 6, :type :ok, :f :append, :key "0", :value "x 6 2 y"} {:process 6, :type :invoke, :f :append, :key "0", :value "x 6 3 y"} {:process 5, :type :ok, :f :get, :key "0", :value "x 9 0 yx 0 0 yx 3 2 yx 7 1 yx 0 4 yx 7 5 yx 7 6 yx 4 13 yx 4 14 yx 2 4 yx 8 4 yx 5 5 yx 5 7 yx 5 12 yx 8 9 yx 8 12 yx 3 3 yx 6 0 yx 1 9 yx 6 2 y"} {:process 5, :type :invoke, :f :get, :key "4", :value nil} {:process 6, :type :ok, :f :append, :key "0", :value "x 6 3 y"} {:process 6, :type :invoke, :f :append, :key "0", :value "x 6 4 y"} {:process 5, :type :ok, :f :get, :key "4", :value "x 5 13 yx 5 14 y"} {:process 5, :type :invoke, :f :put, :key "7", :value "x 5 18 y"} {:process 6, :type :ok, :f :append, :key "0", :value "x 6 4 y"} {:process 6, :type :invoke, :f :get, :key "0", :value nil} {:process 5, :type :ok, :f :put, :key "7", :value "x 5 18 y"} {:process 5, :type :invoke, :f :append, :key "9", :value "x 5 19 y"} {:process 1, :type :ok, :f :get, :key "4", :value "x 5 13 yx 5 14 y"} {:process 1, :type :invoke, :f :get, :key "3", :value nil} {:process 5, :type :ok, :f :append, :key "9", :value "x 5 19 y"} {:process 5, :type :invoke, :f :get, :key "1", :value nil} {:process 1, :type :ok, :f :get, :key "3", :value "x 8 0 yx 5 4 yx 5 8 yx 8 3 yx 9 1 yx 7 1 yx 8 7 yx 3 2 yx 5 7 yx 5 8 yx 5 12 yx 1 8 y"} {:process 1, :type :invoke, :f :append, :key "2", :value "x 1 11 y"} {:process 5, :type :ok, :f :get, :key "1", :value "x 0 0 yx 0 1 yx 0 3 yx 7 4 yx 1 6 yx 1 7 yx 3 5 y"} {:process 5, :type :invoke, :f :append, :key "9", :value "x 5 20 y"} {:process 5, :type :ok, :f :append, :key "9", :value "x 5 20 y"} {:process 5, :type :invoke, :f :put, :key "3", :value "x 5 21 y"} {:process 4, :type :ok, :f :get, :key "5", :value "x 5 11 yx 5 13 yx 2 9 yx 8 5 y"} {:process 4, :type :invoke, :f :get, :key "2", :value nil} {:process 8, :type :ok, :f :get, :key "0", :value "x 9 0 yx 0 0 yx 3 2 yx 7 1 yx 0 4 yx 7 5 yx 7 6 yx 4 13 yx 4 14 yx 2 4 yx 8 4 yx 5 5 yx 5 7 yx 5 12 yx 8 9 yx 8 12 yx 3 3 yx 6 0 yx 1 9 yx 6 2 yx 6 3 yx 6 4 y"} {:process 8, :type :invoke, :f :get, :key "3", :value nil} {:process 0, :type :ok, :f :append, :key "6", :value "x 0 9 y"} {:process 0, :type :invoke, :f :append, :key "7", :value "x 0 10 y"} {:process 2, :type :ok, :f :put, :key "5", :value "x 2 2 y"} {:process 2, :type :invoke, :f :get, :key "9", :value nil} {:process 0, :type :ok, :f :append, :key "7", :value "x 0 10 y"} {:process 0, :type :invoke, :f :append, :key "8", :value "x 0 11 y"} {:process 6, :type :ok, :f :get, :key "0", :value "x 9 0 yx 0 0 yx 3 2 yx 7 1 yx 0 4 yx 7 5 yx 7 6 yx 4 13 yx 4 14 yx 2 4 yx 8 4 yx 5 5 yx 5 7 yx 5 12 yx 8 9 yx 8 12 yx 3 3 yx 6 0 yx 1 9 yx 6 2 yx 6 3 yx 6 4 y"} {:process 6, :type :invoke, :f :append, :key "0", :value "x 6 5 y"} {:process 2, :type :ok, :f :get, :key "9", :value "x 4 4 yx 6 0 yx 3 0 yx 5 0 yx 7 3 yx 2 3 yx 8 2 yx 8 3 yx 6 3 yx 7 2 yx 7 3 yx 4 0 yx 0 6 yx 5 3 yx 1 10 yx 5 16 yx 5 19 yx 5 20 y"} {:process 2, :type :invoke, :f :get, :key "1", :value nil} {:process 6, :type :ok, :f :append, :key "0", :value "x 6 5 y"} {:process 6, :type :invoke, :f :get, :key "7", :value nil} {:process 2, :type :ok, :f :get, :key "1", :value "x 0 0 yx 0 1 yx 0 3 yx 7 4 yx 1 6 yx 1 7 yx 3 5 y"} {:process 2, :type :invoke, :f :put, :key "4", :value "x 2 3 y"} {:process 2, :type :ok, :f :put, :key "4", :value "x 2 3 y"} {:process 2, :type :invoke, :f :append, :key "2", :value "x 2 4 y"} {:process 2, :type :ok, :f :append, :key "2", :value "x 2 4 y"} {:process 2, :type :invoke, :f :put, :key "3", :value "x 2 5 y"} {:process 3, :type :ok, :f :append, :key "1", :value "x 3 5 y"} {:process 3, :type :invoke, :f :append, :key "4", :value "x 3 6 y"} {:process 3, :type :ok, :f :append, :key "4", :value "x 3 6 y"} {:process 3, :type :invoke, :f :get, :key "6", :value nil} {:process 4, :type :ok, :f :get, :key "2", :value "x 5 5 yx 8 13 yx 6 1 yx 5 15 yx 1 11 yx 2 4 y"} {:process 4, :type :invoke, :f :get, :key "2", :value nil} {:process 4, :type :ok, :f :get, :key "2", :value "x 5 5 yx 8 13 yx 6 1 yx 5 15 yx 1 11 yx 2 4 y"} {:process 4, :type :invoke, :f :append, :key "2", :value "x 4 1 y"} {:process 8, :type :ok, :f :get, :key "3", :value "x 5 21 y"} {:process 8, :type :invoke, :f :get, :key "5", :value nil} {:process 8, :type :ok, :f :get, :key "5", :value "x 2 2 y"} {:process 8, :type :invoke, :f :get, :key "8", :value nil} {:process 8, :type :ok, :f :get, :key "8", :value "x 8 8 yx 0 2 yx 0 4 yx 0 7 yx 5 2 yx 3 1 yx 5 17 y"} {:process 8, :type :invoke, :f :get, :key "2", :value nil} {:process 0, :type :ok, :f :append, :key "8", :value "x 0 11 y"} {:process 0, :type :invoke, :f :append, :key "8", :value "x 0 12 y"} {:process 8, :type :ok, :f :get, :key "2", :value "x 5 5 yx 8 13 yx 6 1 yx 5 15 yx 1 11 yx 2 4 yx 4 1 y"} {:process 8, :type :invoke, :f :append, :key "1", :value "x 8 14 y"} {:process 8, :type :ok, :f :append, :key "1", :value "x 8 14 y"} {:process 8, :type :invoke, :f :append, :key "2", :value "x 8 15 y"} {:process 8, :type :ok, :f :append, :key "2", :value "x 8 15 y"} {:process 8, :type :invoke, :f :get, :key "2", :value nil} {:process 8, :type :ok, :f :get, :key "2", :value "x 5 5 yx 8 13 yx 6 1 yx 5 15 yx 1 11 yx 2 4 yx 4 1 yx 8 15 y"} {:process 8, :type :invoke, :f :append, :key "5", :value "x 8 16 y"} {:process 9, :type :ok, :f :get, :key "7", :value "x 5 18 yx 0 10 yx 7 7 y"} {:process 9, :type :invoke, :f :get, :key "8", :value nil} {:process 8, :type :ok, :f :append, :key "5", :value "x 8 16 y"} {:process 8, :type :invoke, :f :get, :key "4", :value nil} {:process 2, :type :ok, :f :put, :key "3", :value "x 2 5 y"} {:process 2, :type :invoke, :f :get, :key "8", :value nil} {:process 9, :type :ok, :f :get, :key "8", :value "x 8 8 yx 0 2 yx 0 4 yx 0 7 yx 5 2 yx 3 1 yx 5 17 yx 0 11 yx 0 12 y"} {:process 9, :type :invoke, :f :get, :key "6", :value nil} {:process 8, :type :ok, :f :get, :key "4", :value "x 2 3 yx 3 6 y"} {:process 8, :type :invoke, :f :append, :key "7", :value "x 8 17 y"} {:process 8, :type :ok, :f :append, :key "7", :value "x 8 17 y"} {:process 8, :type :invoke, :f :get, :key "6", :value nil} {:process 3, :type :ok, :f :get, :key "6", :value "x 7 4 yx 4 11 yx 4 16 yx 4 17 yx 2 8 yx 7 12 yx 5 6 yx 0 9 yx 7 6 yx 5 11 y"} {:process 3, :type :invoke, :f :get, :key "3", :value nil} {:process 3, :type :ok, :f :get, :key "3", :value "x 2 5 y"} {:process 3, :type :invoke, :f :append, :key "5", :value "x 3 7 y"} {:process 3, :type :ok, :f :append, :key "5", :value "x 3 7 y"} {:process 3, :type :invoke, :f :get, :key "9", :value nil} {:process 3, :type :ok, :f :get, :key "9", :value "x 4 4 yx 6 0 yx 3 0 yx 5 0 yx 7 3 yx 2 3 yx 8 2 yx 8 3 yx 6 3 yx 7 2 yx 7 3 yx 4 0 yx 0 6 yx 5 3 yx 1 10 yx 5 16 yx 5 19 yx 5 20 y"} {:process 3, :type :invoke, :f :get, :key "5", :value nil} {:process 3, :type :ok, :f :get, :key "5", :value "x 2 2 yx 8 16 yx 3 7 y"} {:process 3, :type :invoke, :f :append, :key "9", :value "x 3 8 y"} {:process 3, :type :ok, :f :append, :key "9", :value "x 3 8 y"} {:process 3, :type :invoke, :f :put, :key "0", :value "x 3 9 y"} {:process 3, :type :ok, :f :put, :key "0", :value "x 3 9 y"} {:process 3, :type :invoke, :f :get, :key "0", :value nil} {:process 1, :type :ok, :f :append, :key "2", :value "x 1 11 y"} {:process 1, :type :invoke, :f :append, :key "7", :value "x 1 12 y"} {:process 3, :type :ok, :f :get, :key "0", :value "x 3 9 y"} {:process 3, :type :invoke, :f :append, :key "5", :value "x 3 10 y"} {:process 3, :type :ok, :f :append, :key "5", :value "x 3 10 y"} {:process 3, :type :invoke, :f :append, :key "3", :value "x 3 11 y"} {:process 3, :type :ok, :f :append, :key "3", :value "x 3 11 y"} {:process 3, :type :invoke, :f :put, :key "3", :value "x 3 12 y"} {:process 3, :type :ok, :f :put, :key "3", :value "x 3 12 y"} {:process 3, :type :invoke, :f :get, :key "2", :value nil} {:process 3, :type :ok, :f :get, :key "2", :value "x 5 5 yx 8 13 yx 6 1 yx 5 15 yx 1 11 yx 2 4 yx 4 1 yx 8 15 y"} {:process 3, :type :invoke, :f :append, :key "3", :value "x 3 13 y"} {:process 9, :type :ok, :f :get, :key "6", :value "x 7 4 yx 4 11 yx 4 16 yx 4 17 yx 2 8 yx 7 12 yx 5 6 yx 0 9 yx 7 6 yx 5 11 y"} {:process 9, :type :invoke, :f :get, :key "1", :value nil} {:process 7, :type :ok, :f :append, :key "7", :value "x 7 7 y"} {:process 2, :type :ok, :f :get, :key "8", :value "x 8 8 yx 0 2 yx 0 4 yx 0 7 yx 5 2 yx 3 1 yx 5 17 yx 0 11 yx 0 12 y"} {:process 5, :type :ok, :f :put, :key "3", :value "x 5 21 y"} {:process 6, :type :ok, :f :get, :key "7", :value "x 5 18 yx 0 10 yx 7 7 yx 8 17 y"} {:process 0, :type :ok, :f :append, :key "8", :value "x 0 12 y"} {:process 8, :type :ok, :f :get, :key "6", :value "x 7 4 yx 4 11 yx 4 16 yx 4 17 yx 2 8 yx 7 12 yx 5 6 yx 0 9 yx 7 6 yx 5 11 y"} {:process 3, :type :ok, :f :append, :key "3", :value "x 3 13 y"} {:process 1, :type :ok, :f :append, :key "7", :value "x 1 12 y"} {:process 9, :type :ok, :f :get, :key "1", :value "x 0 0 yx 0 1 yx 0 3 yx 7 4 yx 1 6 yx 1 7 yx 3 5 yx 8 14 y"} {:process 4, :type :ok, :f :append, :key "2", :value "x 4 1 y"} ================================================ FILE: courses/dss/linearizability/test_data/c50-bad.txt ================================================ {:process 2, :type :invoke, :f :get, :key "0", :value nil} {:process 0, :type :invoke, :f :append, :key "8", :value "x 0 0 y"} {:process 1, :type :invoke, :f :get, :key "1", :value nil} {:process 21, :type :invoke, :f :append, :key "9", :value "x 21 0 y"} {:process 3, :type :invoke, :f :append, :key "9", :value "x 3 0 y"} {:process 4, :type :invoke, :f :append, :key "8", :value "x 4 0 y"} {:process 5, :type :invoke, :f :append, :key "1", :value "x 5 0 y"} {:process 6, :type :invoke, :f :get, :key "8", :value nil} {:process 7, :type :invoke, :f :get, :key "7", :value nil} {:process 8, :type :invoke, :f :get, :key "6", :value nil} {:process 9, :type :invoke, :f :append, :key "7", :value "x 9 0 y"} {:process 10, :type :invoke, :f :get, :key "1", :value nil} {:process 11, :type :invoke, :f :append, :key "6", :value "x 11 0 y"} {:process 12, :type :invoke, :f :append, :key "6", :value "x 12 0 y"} {:process 49, :type :invoke, :f :append, :key "0", :value "x 49 0 y"} {:process 13, :type :invoke, :f :append, :key "9", :value "x 13 0 y"} {:process 22, :type :invoke, :f :get, :key "0", :value nil} {:process 14, :type :invoke, :f :put, :key "6", :value "x 14 0 y"} {:process 23, :type :invoke, :f :append, :key "8", :value "x 23 0 y"} {:process 15, :type :invoke, :f :get, :key "6", :value nil} {:process 24, :type :invoke, :f :append, :key "9", :value "x 24 0 y"} {:process 16, :type :invoke, :f :append, :key "7", :value "x 16 0 y"} {:process 25, :type :invoke, :f :append, :key "1", :value "x 25 0 y"} {:process 17, :type :invoke, :f :get, :key "2", :value nil} {:process 26, :type :invoke, :f :append, :key "2", :value "x 26 0 y"} {:process 18, :type :invoke, :f :get, :key "3", :value nil} {:process 27, :type :invoke, :f :get, :key "9", :value nil} {:process 19, :type :invoke, :f :get, :key "8", :value nil} {:process 28, :type :invoke, :f :append, :key "0", :value "x 28 0 y"} {:process 29, :type :invoke, :f :put, :key "7", :value "x 29 0 y"} {:process 30, :type :invoke, :f :append, :key "1", :value "x 30 0 y"} {:process 20, :type :invoke, :f :get, :key "5", :value nil} {:process 31, :type :invoke, :f :get, :key "1", :value nil} {:process 40, :type :invoke, :f :get, :key "2", :value nil} {:process 41, :type :invoke, :f :append, :key "9", :value "x 41 0 y"} {:process 32, :type :invoke, :f :append, :key "0", :value "x 32 0 y"} {:process 42, :type :invoke, :f :get, :key "3", :value nil} {:process 33, :type :invoke, :f :append, :key "5", :value "x 33 0 y"} {:process 43, :type :invoke, :f :put, :key "5", :value "x 43 0 y"} {:process 44, :type :invoke, :f :append, :key "4", :value "x 44 0 y"} {:process 45, :type :invoke, :f :append, :key "5", :value "x 45 0 y"} {:process 46, :type :invoke, :f :get, :key "6", :value nil} {:process 47, :type :invoke, :f :get, :key "6", :value nil} {:process 34, :type :invoke, :f :get, :key "5", :value nil} {:process 48, :type :invoke, :f :put, :key "8", :value "x 48 0 y"} {:process 1, :type :ok, :f :get, :key "1", :value ""} {:process 1, :type :invoke, :f :append, :key "8", :value "x 1 0 y"} {:process 35, :type :invoke, :f :get, :key "1", :value nil} {:process 37, :type :invoke, :f :get, :key "7", :value nil} {:process 38, :type :invoke, :f :append, :key "4", :value "x 38 0 y"} {:process 36, :type :invoke, :f :append, :key "9", :value "x 36 0 y"} {:process 39, :type :invoke, :f :get, :key "0", :value nil} {:process 46, :type :ok, :f :get, :key "6", :value ""} {:process 46, :type :invoke, :f :get, :key "8", :value nil} {:process 42, :type :ok, :f :get, :key "3", :value ""} {:process 42, :type :invoke, :f :get, :key "7", :value nil} {:process 42, :type :ok, :f :get, :key "7", :value ""} {:process 42, :type :invoke, :f :get, :key "3", :value nil} {:process 46, :type :ok, :f :get, :key "8", :value ""} {:process 46, :type :invoke, :f :get, :key "5", :value nil} {:process 22, :type :ok, :f :get, :key "0", :value ""} {:process 22, :type :invoke, :f :append, :key "2", :value "x 22 0 y"} {:process 18, :type :ok, :f :get, :key "3", :value ""} {:process 7, :type :ok, :f :get, :key "7", :value ""} {:process 7, :type :invoke, :f :append, :key "5", :value "x 7 0 y"} {:process 18, :type :invoke, :f :get, :key "0", :value nil} {:process 8, :type :ok, :f :get, :key "6", :value ""} {:process 8, :type :invoke, :f :get, :key "9", :value nil} {:process 35, :type :ok, :f :get, :key "1", :value ""} {:process 35, :type :invoke, :f :append, :key "3", :value "x 35 0 y"} {:process 2, :type :ok, :f :get, :key "0", :value ""} {:process 2, :type :invoke, :f :append, :key "0", :value "x 2 0 y"} {:process 19, :type :ok, :f :get, :key "8", :value ""} {:process 19, :type :invoke, :f :get, :key "1", :value nil} {:process 19, :type :ok, :f :get, :key "1", :value ""} {:process 19, :type :invoke, :f :get, :key "0", :value nil} {:process 47, :type :ok, :f :get, :key "6", :value ""} {:process 47, :type :invoke, :f :append, :key "2", :value "x 47 0 y"} {:process 20, :type :ok, :f :get, :key "5", :value ""} {:process 20, :type :invoke, :f :append, :key "3", :value "x 20 0 y"} {:process 15, :type :ok, :f :get, :key "6", :value ""} {:process 15, :type :invoke, :f :append, :key "2", :value "x 15 0 y"} {:process 17, :type :ok, :f :get, :key "2", :value ""} {:process 17, :type :invoke, :f :append, :key "7", :value "x 17 0 y"} {:process 27, :type :ok, :f :get, :key "9", :value ""} {:process 27, :type :invoke, :f :get, :key "5", :value nil} {:process 8, :type :ok, :f :get, :key "9", :value ""} {:process 8, :type :invoke, :f :append, :key "4", :value "x 8 0 y"} {:process 42, :type :ok, :f :get, :key "3", :value ""} {:process 42, :type :invoke, :f :append, :key "3", :value "x 42 0 y"} {:process 31, :type :ok, :f :get, :key "1", :value ""} {:process 31, :type :invoke, :f :append, :key "6", :value "x 31 0 y"} {:process 37, :type :ok, :f :get, :key "7", :value ""} {:process 37, :type :invoke, :f :get, :key "0", :value nil} {:process 46, :type :ok, :f :get, :key "5", :value ""} {:process 46, :type :invoke, :f :get, :key "9", :value nil} {:process 39, :type :ok, :f :get, :key "0", :value ""} {:process 39, :type :invoke, :f :get, :key "7", :value nil} {:process 27, :type :ok, :f :get, :key "5", :value ""} {:process 27, :type :invoke, :f :append, :key "2", :value "x 27 0 y"} {:process 18, :type :ok, :f :get, :key "0", :value ""} {:process 18, :type :invoke, :f :append, :key "9", :value "x 18 0 y"} {:process 39, :type :ok, :f :get, :key "7", :value ""} {:process 39, :type :invoke, :f :get, :key "1", :value nil} {:process 19, :type :ok, :f :get, :key "0", :value ""} {:process 19, :type :invoke, :f :append, :key "8", :value "x 19 0 y"} {:process 39, :type :ok, :f :get, :key "1", :value ""} {:process 39, :type :invoke, :f :append, :key "7", :value "x 39 0 y"} {:process 46, :type :ok, :f :get, :key "9", :value ""} {:process 46, :type :invoke, :f :get, :key "6", :value nil} {:process 46, :type :ok, :f :get, :key "6", :value ""} {:process 46, :type :invoke, :f :put, :key "5", :value "x 46 0 y"} {:process 6, :type :ok, :f :get, :key "8", :value ""} {:process 6, :type :invoke, :f :append, :key "4", :value "x 6 0 y"} {:process 40, :type :ok, :f :get, :key "2", :value ""} {:process 40, :type :invoke, :f :append, :key "1", :value "x 40 0 y"} {:process 37, :type :ok, :f :get, :key "0", :value ""} {:process 37, :type :invoke, :f :get, :key "4", :value nil} {:process 37, :type :ok, :f :get, :key "4", :value ""} {:process 37, :type :invoke, :f :put, :key "0", :value "x 37 0 y"} {:process 34, :type :ok, :f :get, :key "5", :value ""} {:process 34, :type :invoke, :f :append, :key "1", :value "x 34 0 y"} {:process 10, :type :ok, :f :get, :key "1", :value ""} {:process 10, :type :invoke, :f :get, :key "2", :value nil} {:process 10, :type :ok, :f :get, :key "2", :value ""} {:process 10, :type :invoke, :f :append, :key "5", :value "x 10 0 y"} {:process 12, :type :ok, :f :append, :key "6", :value "x 12 0 y"} {:process 12, :type :invoke, :f :get, :key "2", :value nil} {:process 30, :type :ok, :f :append, :key "1", :value "x 30 0 y"} {:process 30, :type :invoke, :f :append, :key "6", :value "x 30 1 y"} {:process 12, :type :ok, :f :get, :key "2", :value ""} {:process 12, :type :invoke, :f :append, :key "7", :value "x 12 1 y"} {:process 26, :type :ok, :f :append, :key "2", :value "x 26 0 y"} {:process 26, :type :invoke, :f :append, :key "4", :value "x 26 1 y"} {:process 30, :type :ok, :f :append, :key "6", :value "x 30 1 y"} {:process 30, :type :invoke, :f :append, :key "0", :value "x 30 2 y"} {:process 12, :type :ok, :f :append, :key "7", :value "x 12 1 y"} {:process 12, :type :invoke, :f :get, :key "9", :value nil} {:process 6, :type :ok, :f :append, :key "4", :value "x 6 0 y"} {:process 6, :type :invoke, :f :append, :key "8", :value "x 6 1 y"} {:process 26, :type :ok, :f :append, :key "4", :value "x 26 1 y"} {:process 26, :type :invoke, :f :get, :key "9", :value nil} {:process 26, :type :ok, :f :get, :key "9", :value ""} {:process 26, :type :invoke, :f :get, :key "7", :value nil} {:process 12, :type :ok, :f :get, :key "9", :value ""} {:process 12, :type :invoke, :f :get, :key "0", :value nil} {:process 2, :type :ok, :f :append, :key "0", :value "x 2 0 y"} {:process 2, :type :invoke, :f :append, :key "0", :value "x 2 1 y"} {:process 30, :type :ok, :f :append, :key "0", :value "x 30 2 y"} {:process 46, :type :ok, :f :put, :key "5", :value "x 46 0 y"} {:process 30, :type :invoke, :f :get, :key "3", :value nil} {:process 46, :type :invoke, :f :get, :key "2", :value nil} {:process 6, :type :ok, :f :append, :key "8", :value "x 6 1 y"} {:process 6, :type :invoke, :f :get, :key "9", :value nil} {:process 12, :type :ok, :f :get, :key "0", :value "x 2 0 yx 30 2 y"} {:process 12, :type :invoke, :f :get, :key "5", :value nil} {:process 30, :type :ok, :f :get, :key "3", :value ""} {:process 30, :type :invoke, :f :append, :key "1", :value "x 30 3 y"} {:process 46, :type :ok, :f :get, :key "2", :value "x 26 0 y"} {:process 46, :type :invoke, :f :append, :key "1", :value "x 46 1 y"} {:process 12, :type :ok, :f :get, :key "5", :value "x 46 0 y"} {:process 12, :type :invoke, :f :get, :key "6", :value nil} {:process 6, :type :ok, :f :get, :key "9", :value ""} {:process 6, :type :invoke, :f :append, :key "9", :value "x 6 2 y"} {:process 46, :type :ok, :f :append, :key "1", :value "x 46 1 y"} {:process 46, :type :invoke, :f :append, :key "4", :value "x 46 2 y"} {:process 12, :type :ok, :f :get, :key "6", :value "x 12 0 yx 30 1 y"} {:process 12, :type :invoke, :f :append, :key "0", :value "x 12 2 y"} {:process 30, :type :ok, :f :append, :key "1", :value "x 30 3 y"} {:process 30, :type :invoke, :f :get, :key "5", :value nil} {:process 12, :type :ok, :f :append, :key "0", :value "x 12 2 y"} {:process 12, :type :invoke, :f :append, :key "8", :value "x 12 3 y"} {:process 46, :type :ok, :f :append, :key "4", :value "x 46 2 y"} {:process 46, :type :invoke, :f :append, :key "5", :value "x 46 3 y"} {:process 6, :type :ok, :f :append, :key "9", :value "x 6 2 y"} {:process 6, :type :invoke, :f :append, :key "5", :value "x 6 3 y"} {:process 6, :type :ok, :f :append, :key "5", :value "x 6 3 y"} {:process 6, :type :invoke, :f :put, :key "3", :value "x 6 4 y"} {:process 13, :type :ok, :f :append, :key "9", :value "x 13 0 y"} {:process 13, :type :invoke, :f :append, :key "1", :value "x 13 1 y"} {:process 36, :type :ok, :f :append, :key "9", :value "x 36 0 y"} {:process 36, :type :invoke, :f :get, :key "7", :value nil} {:process 12, :type :ok, :f :append, :key "8", :value "x 12 3 y"} {:process 12, :type :invoke, :f :append, :key "3", :value "x 12 4 y"} {:process 36, :type :ok, :f :get, :key "7", :value "x 12 1 y"} {:process 36, :type :invoke, :f :append, :key "0", :value "x 36 1 y"} {:process 12, :type :ok, :f :append, :key "3", :value "x 12 4 y"} {:process 12, :type :invoke, :f :append, :key "3", :value "x 12 5 y"} {:process 13, :type :ok, :f :append, :key "1", :value "x 13 1 y"} {:process 13, :type :invoke, :f :get, :key "6", :value nil} {:process 6, :type :ok, :f :put, :key "3", :value "x 6 4 y"} {:process 6, :type :invoke, :f :append, :key "6", :value "x 6 5 y"} {:process 16, :type :ok, :f :append, :key "7", :value "x 16 0 y"} {:process 16, :type :invoke, :f :get, :key "4", :value nil} {:process 10, :type :ok, :f :append, :key "5", :value "x 10 0 y"} {:process 10, :type :invoke, :f :append, :key "7", :value "x 10 1 y"} {:process 3, :type :ok, :f :append, :key "9", :value "x 3 0 y"} {:process 3, :type :invoke, :f :append, :key "4", :value "x 3 1 y"} {:process 16, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 y"} {:process 16, :type :invoke, :f :get, :key "6", :value nil} {:process 13, :type :ok, :f :get, :key "6", :value "x 12 0 yx 30 1 y"} {:process 13, :type :invoke, :f :get, :key "9", :value nil} {:process 19, :type :ok, :f :append, :key "8", :value "x 19 0 y"} {:process 19, :type :invoke, :f :append, :key "5", :value "x 19 1 y"} {:process 6, :type :ok, :f :append, :key "6", :value "x 6 5 y"} {:process 6, :type :invoke, :f :append, :key "0", :value "x 6 6 y"} {:process 26, :type :ok, :f :get, :key "7", :value "x 12 1 y"} {:process 26, :type :invoke, :f :append, :key "0", :value "x 26 2 y"} {:process 12, :type :ok, :f :append, :key "3", :value "x 12 5 y"} {:process 12, :type :invoke, :f :get, :key "1", :value nil} {:process 16, :type :ok, :f :get, :key "6", :value "x 12 0 yx 30 1 yx 6 5 y"} {:process 16, :type :invoke, :f :get, :key "4", :value nil} {:process 6, :type :ok, :f :append, :key "0", :value "x 6 6 y"} {:process 6, :type :invoke, :f :get, :key "9", :value nil} {:process 10, :type :ok, :f :append, :key "7", :value "x 10 1 y"} {:process 10, :type :invoke, :f :get, :key "2", :value nil} {:process 13, :type :ok, :f :get, :key "9", :value "x 6 2 yx 13 0 yx 36 0 yx 3 0 y"} {:process 13, :type :invoke, :f :append, :key "2", :value "x 13 2 y"} {:process 3, :type :ok, :f :append, :key "4", :value "x 3 1 y"} {:process 3, :type :invoke, :f :get, :key "2", :value nil} {:process 3, :type :ok, :f :get, :key "2", :value "x 26 0 y"} {:process 3, :type :invoke, :f :get, :key "4", :value nil} {:process 3, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 y"} {:process 3, :type :invoke, :f :append, :key "8", :value "x 3 2 y"} {:process 6, :type :ok, :f :get, :key "9", :value "x 6 2 yx 13 0 yx 36 0 yx 3 0 y"} {:process 6, :type :invoke, :f :get, :key "7", :value nil} {:process 12, :type :ok, :f :get, :key "1", :value "x 30 0 yx 46 1 yx 30 3 yx 13 1 y"} {:process 12, :type :invoke, :f :append, :key "4", :value "x 12 6 y"} {:process 16, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 y"} {:process 16, :type :invoke, :f :append, :key "4", :value "x 16 1 y"} {:process 10, :type :ok, :f :get, :key "2", :value "x 26 0 y"} {:process 10, :type :invoke, :f :append, :key "3", :value "x 10 2 y"} {:process 13, :type :ok, :f :append, :key "2", :value "x 13 2 y"} {:process 13, :type :invoke, :f :append, :key "0", :value "x 13 3 y"} {:process 12, :type :ok, :f :append, :key "4", :value "x 12 6 y"} {:process 12, :type :invoke, :f :append, :key "0", :value "x 12 7 y"} {:process 10, :type :ok, :f :append, :key "3", :value "x 10 2 y"} {:process 10, :type :invoke, :f :append, :key "6", :value "x 10 3 y"} {:process 15, :type :ok, :f :append, :key "2", :value "x 15 0 y"} {:process 15, :type :invoke, :f :get, :key "5", :value nil} {:process 3, :type :ok, :f :append, :key "8", :value "x 3 2 y"} {:process 3, :type :invoke, :f :append, :key "0", :value "x 3 3 y"} {:process 13, :type :ok, :f :append, :key "0", :value "x 13 3 y"} {:process 13, :type :invoke, :f :get, :key "5", :value nil} {:process 24, :type :ok, :f :append, :key "9", :value "x 24 0 y"} {:process 24, :type :invoke, :f :append, :key "3", :value "x 24 1 y"} {:process 30, :type :ok, :f :get, :key "5", :value "x 46 0 yx 6 3 yx 10 0 yx 19 1 y"} {:process 30, :type :invoke, :f :append, :key "8", :value "x 30 4 y"} {:process 15, :type :ok, :f :get, :key "5", :value "x 46 0 yx 6 3 yx 10 0 yx 19 1 y"} {:process 15, :type :invoke, :f :append, :key "7", :value "x 15 1 y"} {:process 3, :type :ok, :f :append, :key "0", :value "x 3 3 y"} {:process 3, :type :invoke, :f :append, :key "6", :value "x 3 4 y"} {:process 49, :type :ok, :f :append, :key "0", :value "x 49 0 y"} {:process 49, :type :invoke, :f :get, :key "3", :value nil} {:process 13, :type :ok, :f :get, :key "5", :value "x 46 0 yx 6 3 yx 10 0 yx 19 1 y"} {:process 13, :type :invoke, :f :get, :key "6", :value nil} {:process 13, :type :ok, :f :get, :key "6", :value "x 12 0 yx 30 1 yx 6 5 y"} {:process 13, :type :invoke, :f :get, :key "6", :value nil} {:process 13, :type :ok, :f :get, :key "6", :value "x 12 0 yx 30 1 yx 6 5 y"} {:process 13, :type :invoke, :f :put, :key "7", :value "x 13 4 y"} {:process 49, :type :ok, :f :get, :key "3", :value "x 6 4 yx 12 5 yx 10 2 y"} {:process 49, :type :invoke, :f :append, :key "3", :value "x 49 1 y"} {:process 24, :type :ok, :f :append, :key "3", :value "x 24 1 y"} {:process 24, :type :invoke, :f :append, :key "5", :value "x 24 2 y"} {:process 15, :type :ok, :f :append, :key "7", :value "x 15 1 y"} {:process 15, :type :invoke, :f :get, :key "5", :value nil} {:process 49, :type :ok, :f :append, :key "3", :value "x 49 1 y"} {:process 49, :type :invoke, :f :get, :key "8", :value nil} {:process 15, :type :ok, :f :get, :key "5", :value "x 46 0 yx 6 3 yx 10 0 yx 19 1 y"} {:process 15, :type :invoke, :f :append, :key "5", :value "x 15 2 y"} {:process 13, :type :ok, :f :put, :key "7", :value "x 13 4 y"} {:process 13, :type :invoke, :f :append, :key "5", :value "x 13 5 y"} {:process 49, :type :ok, :f :get, :key "8", :value "x 6 1 yx 12 3 yx 19 0 yx 3 2 y"} {:process 49, :type :invoke, :f :append, :key "9", :value "x 49 2 y"} {:process 24, :type :ok, :f :append, :key "5", :value "x 24 2 y"} {:process 24, :type :invoke, :f :get, :key "1", :value nil} {:process 15, :type :ok, :f :append, :key "5", :value "x 15 2 y"} {:process 15, :type :invoke, :f :get, :key "4", :value nil} {:process 15, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 y"} {:process 15, :type :invoke, :f :get, :key "1", :value nil} {:process 6, :type :ok, :f :get, :key "7", :value "x 13 4 y"} {:process 6, :type :invoke, :f :get, :key "5", :value nil} {:process 48, :type :ok, :f :put, :key "8", :value "x 48 0 y"} {:process 48, :type :invoke, :f :append, :key "0", :value "x 48 1 y"} {:process 15, :type :ok, :f :get, :key "1", :value "x 30 0 yx 46 1 yx 30 3 yx 13 1 y"} {:process 15, :type :invoke, :f :append, :key "4", :value "x 15 3 y"} {:process 49, :type :ok, :f :append, :key "9", :value "x 49 2 y"} {:process 49, :type :invoke, :f :append, :key "8", :value "x 49 3 y"} {:process 37, :type :ok, :f :put, :key "0", :value "x 37 0 y"} {:process 37, :type :invoke, :f :get, :key "2", :value nil} {:process 37, :type :ok, :f :get, :key "2", :value "x 26 0 yx 13 2 yx 15 0 y"} {:process 37, :type :invoke, :f :append, :key "8", :value "x 37 1 y"} {:process 6, :type :ok, :f :get, :key "5", :value "x 46 0 yx 6 3 yx 10 0 yx 19 1 yx 24 2 yx 15 2 y"} {:process 6, :type :invoke, :f :append, :key "7", :value "x 6 7 y"} {:process 28, :type :ok, :f :append, :key "0", :value "x 28 0 y"} {:process 28, :type :invoke, :f :get, :key "7", :value nil} {:process 48, :type :ok, :f :append, :key "0", :value "x 48 1 y"} {:process 48, :type :invoke, :f :append, :key "1", :value "x 48 2 y"} {:process 15, :type :ok, :f :append, :key "4", :value "x 15 3 y"} {:process 15, :type :invoke, :f :append, :key "1", :value "x 15 4 y"} {:process 49, :type :ok, :f :append, :key "8", :value "x 49 3 y"} {:process 49, :type :invoke, :f :get, :key "7", :value nil} {:process 8, :type :ok, :f :append, :key "4", :value "x 8 0 y"} {:process 8, :type :invoke, :f :get, :key "2", :value nil} {:process 37, :type :ok, :f :append, :key "8", :value "x 37 1 y"} {:process 37, :type :invoke, :f :append, :key "5", :value "x 37 2 y"} {:process 18, :type :ok, :f :append, :key "9", :value "x 18 0 y"} {:process 18, :type :invoke, :f :append, :key "9", :value "x 18 1 y"} {:process 35, :type :ok, :f :append, :key "3", :value "x 35 0 y"} {:process 35, :type :invoke, :f :get, :key "7", :value nil} {:process 8, :type :ok, :f :get, :key "2", :value "x 26 0 yx 13 2 yx 15 0 y"} {:process 8, :type :invoke, :f :append, :key "2", :value "x 8 1 y"} {:process 35, :type :ok, :f :get, :key "7", :value "x 13 4 y"} {:process 35, :type :invoke, :f :append, :key "0", :value "x 35 1 y"} {:process 18, :type :ok, :f :append, :key "9", :value "x 18 1 y"} {:process 18, :type :invoke, :f :get, :key "0", :value nil} {:process 5, :type :ok, :f :append, :key "1", :value "x 5 0 y"} {:process 5, :type :invoke, :f :append, :key "9", :value "x 5 1 y"} {:process 15, :type :ok, :f :append, :key "1", :value "x 15 4 y"} {:process 15, :type :invoke, :f :append, :key "2", :value "x 15 5 y"} {:process 37, :type :ok, :f :append, :key "5", :value "x 37 2 y"} {:process 37, :type :invoke, :f :append, :key "5", :value "x 37 3 y"} {:process 49, :type :ok, :f :get, :key "7", :value "x 13 4 y"} {:process 49, :type :invoke, :f :get, :key "6", :value nil} {:process 5, :type :ok, :f :append, :key "9", :value "x 5 1 y"} {:process 5, :type :invoke, :f :get, :key "4", :value nil} {:process 18, :type :ok, :f :get, :key "0", :value "x 37 0 yx 28 0 yx 48 1 y"} {:process 18, :type :invoke, :f :get, :key "3", :value nil} {:process 5, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 y"} {:process 5, :type :invoke, :f :get, :key "2", :value nil} {:process 37, :type :ok, :f :append, :key "5", :value "x 37 3 y"} {:process 37, :type :invoke, :f :append, :key "2", :value "x 37 4 y"} {:process 35, :type :ok, :f :append, :key "0", :value "x 35 1 y"} {:process 35, :type :invoke, :f :append, :key "7", :value "x 35 2 y"} {:process 49, :type :ok, :f :get, :key "6", :value "x 14 0 y"} {:process 49, :type :invoke, :f :append, :key "7", :value "x 49 4 y"} {:process 15, :type :ok, :f :append, :key "2", :value "x 15 5 y"} {:process 15, :type :invoke, :f :put, :key "3", :value "x 15 6 y"} {:process 18, :type :ok, :f :get, :key "3", :value "x 6 4 yx 12 5 yx 10 2 yx 24 1 yx 49 1 yx 35 0 y"} {:process 18, :type :invoke, :f :get, :key "2", :value nil} {:process 5, :type :ok, :f :get, :key "2", :value "x 26 0 yx 13 2 yx 15 0 yx 15 5 y"} {:process 5, :type :invoke, :f :put, :key "0", :value "x 5 2 y"} {:process 18, :type :ok, :f :get, :key "2", :value "x 26 0 yx 13 2 yx 15 0 yx 15 5 y"} {:process 18, :type :invoke, :f :append, :key "8", :value "x 18 2 y"} {:process 37, :type :ok, :f :append, :key "2", :value "x 37 4 y"} {:process 37, :type :invoke, :f :get, :key "1", :value nil} {:process 35, :type :ok, :f :append, :key "7", :value "x 35 2 y"} {:process 35, :type :invoke, :f :get, :key "5", :value nil} {:process 35, :type :ok, :f :get, :key "5", :value "x 46 0 yx 6 3 yx 10 0 yx 19 1 yx 24 2 yx 15 2 yx 33 0 yx 37 2 yx 37 3 y"} {:process 35, :type :invoke, :f :get, :key "5", :value nil} {:process 24, :type :ok, :f :get, :key "1", :value "x 30 0 yx 46 1 yx 30 3 yx 13 1 yx 5 0 yx 15 4 yx 34 0 y"} {:process 24, :type :invoke, :f :append, :key "7", :value "x 24 3 y"} {:process 49, :type :ok, :f :append, :key "7", :value "x 49 4 y"} {:process 5, :type :ok, :f :put, :key "0", :value "x 5 2 y"} {:process 49, :type :invoke, :f :append, :key "3", :value "x 49 5 y"} {:process 5, :type :invoke, :f :get, :key "5", :value nil} {:process 15, :type :ok, :f :put, :key "3", :value "x 15 6 y"} {:process 15, :type :invoke, :f :get, :key "6", :value nil} {:process 37, :type :ok, :f :get, :key "1", :value "x 30 0 yx 46 1 yx 30 3 yx 13 1 yx 5 0 yx 15 4 yx 34 0 y"} {:process 37, :type :invoke, :f :get, :key "8", :value nil} {:process 18, :type :ok, :f :append, :key "8", :value "x 18 2 y"} {:process 18, :type :invoke, :f :append, :key "1", :value "x 18 3 y"} {:process 21, :type :ok, :f :append, :key "9", :value "x 21 0 y"} {:process 21, :type :invoke, :f :get, :key "6", :value nil} {:process 15, :type :ok, :f :get, :key "6", :value "x 14 0 y"} {:process 15, :type :invoke, :f :append, :key "7", :value "x 15 7 y"} {:process 21, :type :ok, :f :get, :key "6", :value "x 14 0 y"} {:process 21, :type :invoke, :f :get, :key "1", :value nil} {:process 37, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 y"} {:process 37, :type :invoke, :f :get, :key "9", :value nil} {:process 18, :type :ok, :f :append, :key "1", :value "x 18 3 y"} {:process 18, :type :invoke, :f :get, :key "6", :value nil} {:process 37, :type :ok, :f :get, :key "9", :value "x 6 2 yx 13 0 yx 36 0 yx 3 0 yx 24 0 yx 49 2 yx 18 0 yx 18 1 yx 5 1 yx 21 0 y"} {:process 37, :type :invoke, :f :get, :key "0", :value nil} {:process 49, :type :ok, :f :append, :key "3", :value "x 49 5 y"} {:process 49, :type :invoke, :f :append, :key "3", :value "x 49 6 y"} {:process 18, :type :ok, :f :get, :key "6", :value "x 14 0 y"} {:process 18, :type :invoke, :f :get, :key "9", :value nil} {:process 21, :type :ok, :f :get, :key "1", :value "x 30 0 yx 46 1 yx 30 3 yx 13 1 yx 5 0 yx 15 4 yx 34 0 yx 25 0 yx 18 3 y"} {:process 21, :type :invoke, :f :append, :key "7", :value "x 21 1 y"} {:process 0, :type :ok, :f :append, :key "8", :value "x 0 0 y"} {:process 0, :type :invoke, :f :append, :key "3", :value "x 0 1 y"} {:process 27, :type :ok, :f :append, :key "2", :value "x 27 0 y"} {:process 27, :type :invoke, :f :append, :key "7", :value "x 27 1 y"} {:process 18, :type :ok, :f :get, :key "9", :value "x 6 2 yx 13 0 yx 36 0 yx 3 0 yx 24 0 yx 49 2 yx 18 0 yx 18 1 yx 5 1 yx 21 0 y"} {:process 18, :type :invoke, :f :append, :key "9", :value "x 18 4 y"} {:process 15, :type :ok, :f :append, :key "7", :value "x 15 7 y"} {:process 15, :type :invoke, :f :get, :key "6", :value nil} {:process 28, :type :ok, :f :get, :key "7", :value "x 13 4 yx 35 2 yx 49 4 y"} {:process 28, :type :invoke, :f :get, :key "4", :value nil} {:process 49, :type :ok, :f :append, :key "3", :value "x 49 6 y"} {:process 49, :type :invoke, :f :get, :key "1", :value nil} {:process 15, :type :ok, :f :get, :key "6", :value "x 14 0 y"} {:process 15, :type :invoke, :f :get, :key "2", :value nil} {:process 0, :type :ok, :f :append, :key "3", :value "x 0 1 y"} {:process 0, :type :invoke, :f :put, :key "2", :value "x 0 2 y"} {:process 21, :type :ok, :f :append, :key "7", :value "x 21 1 y"} {:process 21, :type :invoke, :f :append, :key "0", :value "x 21 2 y"} {:process 27, :type :ok, :f :append, :key "7", :value "x 27 1 y"} {:process 27, :type :invoke, :f :append, :key "4", :value "x 27 2 y"} {:process 28, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 y"} {:process 28, :type :invoke, :f :append, :key "0", :value "x 28 1 y"} {:process 18, :type :ok, :f :append, :key "9", :value "x 18 4 y"} {:process 18, :type :invoke, :f :append, :key "8", :value "x 18 5 y"} {:process 0, :type :ok, :f :put, :key "2", :value "x 0 2 y"} {:process 0, :type :invoke, :f :append, :key "5", :value "x 0 3 y"} {:process 21, :type :ok, :f :append, :key "0", :value "x 21 2 y"} {:process 21, :type :invoke, :f :append, :key "8", :value "x 21 3 y"} {:process 15, :type :ok, :f :get, :key "2", :value "x 0 2 y"} {:process 15, :type :invoke, :f :put, :key "0", :value "x 15 8 y"} {:process 18, :type :ok, :f :append, :key "8", :value "x 18 5 y"} {:process 18, :type :invoke, :f :append, :key "9", :value "x 18 6 y"} {:process 0, :type :ok, :f :append, :key "5", :value "x 0 3 y"} {:process 0, :type :invoke, :f :get, :key "3", :value nil} {:process 27, :type :ok, :f :append, :key "4", :value "x 27 2 y"} {:process 27, :type :invoke, :f :append, :key "8", :value "x 27 3 y"} {:process 0, :type :ok, :f :get, :key "3", :value "x 15 6 yx 49 5 yx 49 6 yx 0 1 y"} {:process 0, :type :invoke, :f :append, :key "8", :value "x 0 4 y"} {:process 18, :type :ok, :f :append, :key "9", :value "x 18 6 y"} {:process 18, :type :invoke, :f :get, :key "3", :value nil} {:process 4, :type :ok, :f :append, :key "8", :value "x 4 0 y"} {:process 4, :type :invoke, :f :append, :key "3", :value "x 4 1 y"} {:process 18, :type :ok, :f :get, :key "3", :value "x 15 6 yx 49 5 yx 49 6 yx 0 1 y"} {:process 18, :type :invoke, :f :get, :key "4", :value nil} {:process 11, :type :ok, :f :append, :key "6", :value "x 11 0 y"} {:process 11, :type :invoke, :f :append, :key "2", :value "x 11 1 y"} {:process 21, :type :ok, :f :append, :key "8", :value "x 21 3 y"} {:process 21, :type :invoke, :f :get, :key "8", :value nil} {:process 21, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 y"} {:process 21, :type :invoke, :f :get, :key "0", :value nil} {:process 15, :type :ok, :f :put, :key "0", :value "x 15 8 y"} {:process 15, :type :invoke, :f :get, :key "0", :value nil} {:process 0, :type :ok, :f :append, :key "8", :value "x 0 4 y"} {:process 0, :type :invoke, :f :get, :key "9", :value nil} {:process 21, :type :ok, :f :get, :key "0", :value "x 15 8 y"} {:process 21, :type :invoke, :f :get, :key "1", :value nil} {:process 18, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 y"} {:process 18, :type :invoke, :f :append, :key "8", :value "x 18 7 y"} {:process 4, :type :ok, :f :append, :key "3", :value "x 4 1 y"} {:process 4, :type :invoke, :f :get, :key "7", :value nil} {:process 37, :type :ok, :f :get, :key "0", :value "x 15 8 y"} {:process 37, :type :invoke, :f :get, :key "3", :value nil} {:process 37, :type :ok, :f :get, :key "3", :value "x 15 6 yx 49 5 yx 49 6 yx 0 1 y"} {:process 37, :type :invoke, :f :put, :key "3", :value "x 37 5 y"} {:process 21, :type :ok, :f :get, :key "1", :value "x 30 0 yx 46 1 yx 30 3 yx 13 1 yx 5 0 yx 15 4 yx 34 0 yx 25 0 yx 18 3 y"} {:process 21, :type :invoke, :f :get, :key "5", :value nil} {:process 0, :type :ok, :f :get, :key "9", :value "x 6 2 yx 13 0 yx 36 0 yx 3 0 yx 24 0 yx 49 2 yx 18 0 yx 18 1 yx 5 1 yx 21 0 yx 18 4 yx 18 6 y"} {:process 0, :type :invoke, :f :get, :key "0", :value nil} {:process 0, :type :ok, :f :get, :key "0", :value "x 15 8 y"} {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 5 y"} {:process 11, :type :ok, :f :append, :key "2", :value "x 11 1 y"} {:process 11, :type :invoke, :f :get, :key "2", :value nil} {:process 31, :type :ok, :f :append, :key "6", :value "x 31 0 y"} {:process 31, :type :invoke, :f :append, :key "3", :value "x 31 1 y"} {:process 31, :type :ok, :f :append, :key "3", :value "x 31 1 y"} {:process 31, :type :invoke, :f :append, :key "7", :value "x 31 2 y"} {:process 49, :type :ok, :f :get, :key "1", :value "x 30 0 yx 46 1 yx 30 3 yx 13 1 yx 5 0 yx 15 4 yx 34 0 yx 25 0 yx 18 3 y"} {:process 49, :type :invoke, :f :append, :key "4", :value "x 49 7 y"} {:process 31, :type :ok, :f :append, :key "7", :value "x 31 2 y"} {:process 31, :type :invoke, :f :get, :key "7", :value nil} {:process 35, :type :ok, :f :get, :key "5", :value "x 46 0 yx 6 3 yx 10 0 yx 19 1 yx 24 2 yx 15 2 yx 33 0 yx 37 2 yx 37 3 yx 0 3 y"} {:process 35, :type :invoke, :f :get, :key "9", :value nil} {:process 7, :type :ok, :f :append, :key "5", :value "x 7 0 y"} {:process 7, :type :invoke, :f :get, :key "3", :value nil} {:process 5, :type :ok, :f :get, :key "5", :value "x 46 0 yx 6 3 yx 10 0 yx 19 1 yx 24 2 yx 15 2 yx 33 0 yx 37 2 yx 37 3 yx 0 3 y"} {:process 5, :type :invoke, :f :append, :key "4", :value "x 5 3 y"} {:process 35, :type :ok, :f :get, :key "9", :value "x 6 2 yx 13 0 yx 36 0 yx 3 0 yx 24 0 yx 49 2 yx 18 0 yx 18 1 yx 5 1 yx 21 0 yx 18 4 yx 18 6 y"} {:process 35, :type :invoke, :f :append, :key "5", :value "x 35 3 y"} {:process 15, :type :ok, :f :get, :key "0", :value "x 15 8 y"} {:process 15, :type :invoke, :f :get, :key "0", :value nil} {:process 4, :type :ok, :f :get, :key "7", :value "x 13 4 yx 35 2 yx 49 4 yx 15 7 yx 21 1 yx 27 1 yx 31 2 y"} {:process 4, :type :invoke, :f :append, :key "2", :value "x 4 2 y"} {:process 21, :type :ok, :f :get, :key "5", :value "x 46 0 yx 6 3 yx 10 0 yx 19 1 yx 24 2 yx 15 2 yx 33 0 yx 37 2 yx 37 3 yx 0 3 y"} {:process 21, :type :invoke, :f :append, :key "5", :value "x 21 4 y"} {:process 15, :type :ok, :f :get, :key "0", :value "x 15 8 y"} {:process 15, :type :invoke, :f :get, :key "4", :value nil} {:process 31, :type :ok, :f :get, :key "7", :value "x 13 4 yx 35 2 yx 49 4 yx 15 7 yx 21 1 yx 27 1 yx 31 2 y"} {:process 31, :type :invoke, :f :get, :key "3", :value nil} {:process 7, :type :ok, :f :get, :key "3", :value "x 15 6 yx 49 5 yx 49 6 yx 0 1 yx 4 1 yx 20 0 yx 31 1 y"} {:process 7, :type :invoke, :f :append, :key "4", :value "x 7 1 y"} {:process 15, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 y"} {:process 15, :type :invoke, :f :get, :key "4", :value nil} {:process 11, :type :ok, :f :get, :key "2", :value "x 0 2 yx 11 1 y"} {:process 11, :type :invoke, :f :append, :key "8", :value "x 11 2 y"} {:process 15, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 y"} {:process 15, :type :invoke, :f :append, :key "5", :value "x 15 9 y"} {:process 31, :type :ok, :f :get, :key "3", :value "x 15 6 yx 49 5 yx 49 6 yx 0 1 yx 4 1 yx 20 0 yx 31 1 y"} {:process 31, :type :invoke, :f :get, :key "9", :value nil} {:process 31, :type :ok, :f :get, :key "9", :value "x 6 2 yx 13 0 yx 36 0 yx 3 0 yx 24 0 yx 49 2 yx 18 0 yx 18 1 yx 5 1 yx 21 0 yx 18 4 yx 18 6 y"} {:process 31, :type :invoke, :f :append, :key "1", :value "x 31 3 y"} {:process 47, :type :ok, :f :append, :key "2", :value "x 47 0 y"} {:process 47, :type :invoke, :f :get, :key "5", :value nil} {:process 19, :type :ok, :f :append, :key "5", :value "x 19 1 y"} {:process 19, :type :invoke, :f :append, :key "4", :value "x 19 2 y"} {:process 47, :type :ok, :f :get, :key "5", :value "x 43 0 y"} {:process 47, :type :invoke, :f :append, :key "2", :value "x 47 1 y"} {:process 19, :type :ok, :f :append, :key "4", :value "x 19 2 y"} {:process 19, :type :invoke, :f :append, :key "4", :value "x 19 3 y"} {:process 47, :type :ok, :f :append, :key "2", :value "x 47 1 y"} {:process 47, :type :invoke, :f :append, :key "7", :value "x 47 2 y"} {:process 9, :type :ok, :f :append, :key "7", :value "x 9 0 y"} {:process 9, :type :invoke, :f :get, :key "3", :value nil} {:process 34, :type :ok, :f :append, :key "1", :value "x 34 0 y"} {:process 34, :type :invoke, :f :append, :key "7", :value "x 34 1 y"} {:process 6, :type :ok, :f :append, :key "7", :value "x 6 7 y"} {:process 6, :type :invoke, :f :get, :key "0", :value nil} {:process 21, :type :ok, :f :append, :key "5", :value "x 21 4 y"} {:process 21, :type :invoke, :f :append, :key "2", :value "x 21 5 y"} {:process 19, :type :ok, :f :append, :key "4", :value "x 19 3 y"} {:process 19, :type :invoke, :f :append, :key "0", :value "x 19 4 y"} {:process 47, :type :ok, :f :append, :key "7", :value "x 47 2 y"} {:process 21, :type :ok, :f :append, :key "2", :value "x 21 5 y"} {:process 47, :type :invoke, :f :append, :key "6", :value "x 47 3 y"} {:process 21, :type :invoke, :f :get, :key "9", :value nil} {:process 34, :type :ok, :f :append, :key "7", :value "x 34 1 y"} {:process 34, :type :invoke, :f :append, :key "3", :value "x 34 2 y"} {:process 6, :type :ok, :f :get, :key "0", :value "x 15 8 y"} {:process 6, :type :invoke, :f :append, :key "5", :value "x 6 8 y"} {:process 6, :type :ok, :f :append, :key "5", :value "x 6 8 y"} {:process 6, :type :invoke, :f :get, :key "4", :value nil} {:process 21, :type :ok, :f :get, :key "9", :value "x 6 2 yx 13 0 yx 36 0 yx 3 0 yx 24 0 yx 49 2 yx 18 0 yx 18 1 yx 5 1 yx 21 0 yx 18 4 yx 18 6 y"} {:process 21, :type :invoke, :f :get, :key "1", :value nil} {:process 47, :type :ok, :f :append, :key "6", :value "x 47 3 y"} {:process 47, :type :invoke, :f :get, :key "4", :value nil} {:process 6, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 y"} {:process 6, :type :invoke, :f :append, :key "2", :value "x 6 9 y"} {:process 47, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 y"} {:process 47, :type :invoke, :f :append, :key "1", :value "x 47 4 y"} {:process 21, :type :ok, :f :get, :key "1", :value "x 30 0 yx 46 1 yx 30 3 yx 13 1 yx 5 0 yx 15 4 yx 34 0 yx 25 0 yx 18 3 y"} {:process 21, :type :invoke, :f :get, :key "8", :value nil} {:process 41, :type :ok, :f :append, :key "9", :value "x 41 0 y"} {:process 41, :type :invoke, :f :append, :key "5", :value "x 41 1 y"} {:process 21, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 y"} {:process 21, :type :invoke, :f :append, :key "6", :value "x 21 6 y"} {:process 29, :type :ok, :f :put, :key "7", :value "x 29 0 y"} {:process 29, :type :invoke, :f :append, :key "4", :value "x 29 1 y"} {:process 6, :type :ok, :f :append, :key "2", :value "x 6 9 y"} {:process 6, :type :invoke, :f :append, :key "3", :value "x 6 10 y"} {:process 21, :type :ok, :f :append, :key "6", :value "x 21 6 y"} {:process 21, :type :invoke, :f :append, :key "5", :value "x 21 7 y"} {:process 47, :type :ok, :f :append, :key "1", :value "x 47 4 y"} {:process 47, :type :invoke, :f :get, :key "2", :value nil} {:process 41, :type :ok, :f :append, :key "5", :value "x 41 1 y"} {:process 41, :type :invoke, :f :append, :key "2", :value "x 41 2 y"} {:process 6, :type :ok, :f :append, :key "3", :value "x 6 10 y"} {:process 6, :type :invoke, :f :get, :key "1", :value nil} {:process 29, :type :ok, :f :append, :key "4", :value "x 29 1 y"} {:process 29, :type :invoke, :f :append, :key "3", :value "x 29 2 y"} {:process 33, :type :ok, :f :append, :key "5", :value "x 33 0 y"} {:process 33, :type :invoke, :f :get, :key "3", :value nil} {:process 32, :type :ok, :f :append, :key "0", :value "x 32 0 y"} {:process 32, :type :invoke, :f :append, :key "5", :value "x 32 1 y"} {:process 41, :type :ok, :f :append, :key "2", :value "x 41 2 y"} {:process 41, :type :invoke, :f :get, :key "8", :value nil} {:process 41, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 y"} {:process 41, :type :invoke, :f :get, :key "8", :value nil} {:process 33, :type :ok, :f :get, :key "3", :value "x 15 6 yx 49 5 yx 49 6 yx 0 1 yx 4 1 yx 20 0 yx 31 1 yx 34 2 yx 6 10 y"} {:process 33, :type :invoke, :f :append, :key "0", :value "x 33 1 y"} {:process 9, :type :ok, :f :get, :key "3", :value "x 15 6 yx 49 5 yx 49 6 yx 0 1 yx 4 1 yx 20 0 yx 31 1 yx 34 2 y"} {:process 9, :type :invoke, :f :put, :key "6", :value "x 9 1 y"} {:process 10, :type :ok, :f :append, :key "6", :value "x 10 3 y"} {:process 10, :type :invoke, :f :get, :key "4", :value nil} {:process 6, :type :ok, :f :get, :key "1", :value "x 30 0 yx 46 1 yx 30 3 yx 13 1 yx 5 0 yx 15 4 yx 34 0 yx 25 0 yx 18 3 yx 47 4 y"} {:process 6, :type :invoke, :f :append, :key "6", :value "x 6 11 y"} {:process 8, :type :ok, :f :append, :key "2", :value "x 8 1 y"} {:process 8, :type :invoke, :f :append, :key "9", :value "x 8 2 y"} {:process 32, :type :ok, :f :append, :key "5", :value "x 32 1 y"} {:process 32, :type :invoke, :f :append, :key "3", :value "x 32 2 y"} {:process 49, :type :ok, :f :append, :key "4", :value "x 49 7 y"} {:process 49, :type :invoke, :f :append, :key "2", :value "x 49 8 y"} {:process 17, :type :ok, :f :append, :key "7", :value "x 17 0 y"} {:process 17, :type :invoke, :f :put, :key "3", :value "x 17 1 y"} {:process 10, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 y"} {:process 10, :type :invoke, :f :get, :key "4", :value nil} {:process 6, :type :ok, :f :append, :key "6", :value "x 6 11 y"} {:process 6, :type :invoke, :f :get, :key "0", :value nil} {:process 6, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 y"} {:process 6, :type :invoke, :f :get, :key "8", :value nil} {:process 8, :type :ok, :f :append, :key "9", :value "x 8 2 y"} {:process 8, :type :invoke, :f :get, :key "4", :value nil} {:process 33, :type :ok, :f :append, :key "0", :value "x 33 1 y"} {:process 33, :type :invoke, :f :get, :key "2", :value nil} {:process 10, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 y"} {:process 10, :type :invoke, :f :append, :key "7", :value "x 10 4 y"} {:process 8, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 y"} {:process 8, :type :invoke, :f :get, :key "1", :value nil} {:process 6, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 y"} {:process 6, :type :invoke, :f :get, :key "8", :value nil} {:process 17, :type :ok, :f :put, :key "3", :value "x 17 1 y"} {:process 17, :type :invoke, :f :append, :key "6", :value "x 17 2 y"} {:process 32, :type :ok, :f :append, :key "3", :value "x 32 2 y"} {:process 32, :type :invoke, :f :append, :key "4", :value "x 32 3 y"} {:process 8, :type :ok, :f :get, :key "1", :value "x 30 0 yx 46 1 yx 30 3 yx 13 1 yx 5 0 yx 15 4 yx 34 0 yx 25 0 yx 18 3 yx 47 4 y"} {:process 8, :type :invoke, :f :get, :key "8", :value nil} {:process 8, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 y"} {:process 8, :type :invoke, :f :append, :key "0", :value "x 8 3 y"} {:process 32, :type :ok, :f :append, :key "4", :value "x 32 3 y"} {:process 32, :type :invoke, :f :append, :key "4", :value "x 32 4 y"} {:process 6, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 y"} {:process 6, :type :invoke, :f :get, :key "0", :value nil} {:process 17, :type :ok, :f :append, :key "6", :value "x 17 2 y"} {:process 17, :type :invoke, :f :get, :key "0", :value nil} {:process 17, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 y"} {:process 17, :type :invoke, :f :append, :key "1", :value "x 17 3 y"} {:process 6, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 y"} {:process 6, :type :invoke, :f :append, :key "4", :value "x 6 12 y"} {:process 47, :type :ok, :f :get, :key "2", :value "x 0 2 yx 11 1 yx 47 0 yx 47 1 yx 21 5 yx 6 9 yx 41 2 yx 8 1 y"} {:process 47, :type :invoke, :f :get, :key "6", :value nil} {:process 20, :type :ok, :f :append, :key "3", :value "x 20 0 y"} {:process 20, :type :invoke, :f :append, :key "3", :value "x 20 1 y"} {:process 1, :type :ok, :f :append, :key "8", :value "x 1 0 y"} {:process 1, :type :invoke, :f :append, :key "7", :value "x 1 1 y"} {:process 17, :type :ok, :f :append, :key "1", :value "x 17 3 y"} {:process 17, :type :invoke, :f :get, :key "6", :value nil} {:process 3, :type :ok, :f :append, :key "6", :value "x 3 4 y"} {:process 3, :type :invoke, :f :get, :key "1", :value nil} {:process 23, :type :ok, :f :append, :key "8", :value "x 23 0 y"} {:process 23, :type :invoke, :f :get, :key "9", :value nil} {:process 1, :type :ok, :f :append, :key "7", :value "x 1 1 y"} {:process 1, :type :invoke, :f :append, :key "1", :value "x 1 2 y"} {:process 41, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 yx 1 0 y"} {:process 41, :type :invoke, :f :append, :key "6", :value "x 41 3 y"} {:process 23, :type :ok, :f :get, :key "9", :value "x 6 2 yx 13 0 yx 36 0 yx 3 0 yx 24 0 yx 49 2 yx 18 0 yx 18 1 yx 5 1 yx 21 0 yx 18 4 yx 18 6 yx 41 0 yx 8 2 y"} {:process 23, :type :invoke, :f :get, :key "2", :value nil} {:process 17, :type :ok, :f :get, :key "6", :value "x 14 0 yx 11 0 yx 31 0 yx 47 3 yx 21 6 yx 10 3 yx 6 11 yx 17 2 y"} {:process 17, :type :invoke, :f :append, :key "9", :value "x 17 4 y"} {:process 6, :type :ok, :f :append, :key "4", :value "x 6 12 y"} {:process 6, :type :invoke, :f :append, :key "2", :value "x 6 13 y"} {:process 20, :type :ok, :f :append, :key "3", :value "x 20 1 y"} {:process 20, :type :invoke, :f :get, :key "5", :value nil} {:process 47, :type :ok, :f :get, :key "6", :value "x 14 0 yx 11 0 yx 31 0 yx 47 3 yx 21 6 yx 10 3 yx 6 11 yx 17 2 y"} {:process 47, :type :invoke, :f :put, :key "8", :value "x 47 5 y"} {:process 20, :type :ok, :f :get, :key "5", :value "x 43 0 yx 21 4 yx 6 8 yx 41 1 yx 32 1 y"} {:process 20, :type :invoke, :f :get, :key "3", :value nil} {:process 2, :type :ok, :f :append, :key "0", :value "x 2 1 y"} {:process 2, :type :invoke, :f :get, :key "7", :value nil} {:process 6, :type :ok, :f :append, :key "2", :value "x 6 13 y"} {:process 6, :type :invoke, :f :append, :key "7", :value "x 6 14 y"} {:process 33, :type :ok, :f :get, :key "2", :value "x 0 2 yx 11 1 yx 47 0 yx 47 1 yx 21 5 yx 6 9 yx 41 2 yx 8 1 y"} {:process 33, :type :invoke, :f :append, :key "9", :value "x 33 2 y"} {:process 3, :type :ok, :f :get, :key "1", :value "x 30 0 yx 46 1 yx 30 3 yx 13 1 yx 5 0 yx 15 4 yx 34 0 yx 25 0 yx 18 3 yx 47 4 yx 17 3 y"} {:process 3, :type :invoke, :f :append, :key "4", :value "x 3 5 y"} {:process 1, :type :ok, :f :append, :key "1", :value "x 1 2 y"} {:process 1, :type :invoke, :f :get, :key "3", :value nil} {:process 2, :type :ok, :f :get, :key "7", :value "x 29 0 yx 17 0 yx 10 4 yx 1 1 y"} {:process 2, :type :invoke, :f :append, :key "6", :value "x 2 2 y"} {:process 23, :type :ok, :f :get, :key "2", :value "x 0 2 yx 11 1 yx 47 0 yx 47 1 yx 21 5 yx 6 9 yx 41 2 yx 8 1 yx 6 13 y"} {:process 23, :type :invoke, :f :append, :key "6", :value "x 23 1 y"} {:process 17, :type :ok, :f :append, :key "9", :value "x 17 4 y"} {:process 17, :type :invoke, :f :append, :key "3", :value "x 17 5 y"} {:process 20, :type :ok, :f :get, :key "3", :value "x 17 1 yx 32 2 yx 20 1 y"} {:process 20, :type :invoke, :f :append, :key "0", :value "x 20 2 y"} {:process 39, :type :ok, :f :append, :key "7", :value "x 39 0 y"} {:process 39, :type :invoke, :f :append, :key "4", :value "x 39 1 y"} {:process 1, :type :ok, :f :get, :key "3", :value "x 17 1 yx 32 2 yx 20 1 y"} {:process 1, :type :invoke, :f :get, :key "0", :value nil} {:process 3, :type :ok, :f :append, :key "4", :value "x 3 5 y"} {:process 2, :type :ok, :f :append, :key "6", :value "x 2 2 y"} {:process 3, :type :invoke, :f :get, :key "2", :value nil} {:process 2, :type :invoke, :f :get, :key "4", :value nil} {:process 1, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 y"} {:process 1, :type :invoke, :f :append, :key "0", :value "x 1 3 y"} {:process 20, :type :ok, :f :append, :key "0", :value "x 20 2 y"} {:process 20, :type :invoke, :f :append, :key "2", :value "x 20 3 y"} {:process 39, :type :ok, :f :append, :key "4", :value "x 39 1 y"} {:process 39, :type :invoke, :f :get, :key "8", :value nil} {:process 2, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 yx 32 3 yx 5 3 yx 6 12 yx 3 5 yx 39 1 y"} {:process 2, :type :invoke, :f :get, :key "0", :value nil} {:process 3, :type :ok, :f :get, :key "2", :value "x 0 2 yx 11 1 yx 47 0 yx 47 1 yx 21 5 yx 6 9 yx 41 2 yx 8 1 yx 6 13 y"} {:process 3, :type :invoke, :f :get, :key "9", :value nil} {:process 39, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 yx 1 0 yx 18 7 yx 23 0 y"} {:process 39, :type :invoke, :f :append, :key "1", :value "x 39 2 y"} {:process 2, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 y"} {:process 2, :type :invoke, :f :append, :key "0", :value "x 2 3 y"} {:process 1, :type :ok, :f :append, :key "0", :value "x 1 3 y"} {:process 1, :type :invoke, :f :get, :key "3", :value nil} {:process 20, :type :ok, :f :append, :key "2", :value "x 20 3 y"} {:process 20, :type :invoke, :f :append, :key "5", :value "x 20 4 y"} {:process 1, :type :ok, :f :get, :key "3", :value "x 17 1 yx 32 2 yx 20 1 y"} {:process 1, :type :invoke, :f :get, :key "4", :value nil} {:process 3, :type :ok, :f :get, :key "9", :value "x 6 2 yx 13 0 yx 36 0 yx 3 0 yx 24 0 yx 49 2 yx 18 0 yx 18 1 yx 5 1 yx 21 0 yx 18 4 yx 18 6 yx 41 0 yx 8 2 yx 17 4 y"} {:process 3, :type :invoke, :f :get, :key "2", :value nil} {:process 11, :type :ok, :f :append, :key "8", :value "x 11 2 y"} {:process 11, :type :invoke, :f :append, :key "0", :value "x 11 3 y"} {:process 39, :type :ok, :f :append, :key "1", :value "x 39 2 y"} {:process 39, :type :invoke, :f :get, :key "3", :value nil} {:process 3, :type :ok, :f :get, :key "2", :value "x 0 2 yx 11 1 yx 47 0 yx 47 1 yx 21 5 yx 6 9 yx 41 2 yx 8 1 yx 6 13 yx 20 3 y"} {:process 3, :type :invoke, :f :append, :key "1", :value "x 3 6 y"} {:process 20, :type :ok, :f :append, :key "5", :value "x 20 4 y"} {:process 20, :type :invoke, :f :append, :key "9", :value "x 20 5 y"} {:process 1, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 yx 32 3 yx 5 3 yx 6 12 yx 3 5 yx 39 1 y"} {:process 1, :type :invoke, :f :get, :key "0", :value nil} {:process 40, :type :ok, :f :append, :key "1", :value "x 40 0 y"} {:process 40, :type :invoke, :f :append, :key "0", :value "x 40 1 y"} {:process 11, :type :ok, :f :append, :key "0", :value "x 11 3 y"} {:process 11, :type :invoke, :f :append, :key "6", :value "x 11 4 y"} {:process 42, :type :ok, :f :append, :key "3", :value "x 42 0 y"} {:process 42, :type :invoke, :f :append, :key "9", :value "x 42 1 y"} {:process 44, :type :ok, :f :append, :key "4", :value "x 44 0 y"} {:process 44, :type :invoke, :f :append, :key "2", :value "x 44 1 y"} {:process 20, :type :ok, :f :append, :key "9", :value "x 20 5 y"} {:process 20, :type :invoke, :f :append, :key "6", :value "x 20 6 y"} {:process 3, :type :ok, :f :append, :key "1", :value "x 3 6 y"} {:process 3, :type :invoke, :f :append, :key "3", :value "x 3 7 y"} {:process 42, :type :ok, :f :append, :key "9", :value "x 42 1 y"} {:process 42, :type :invoke, :f :get, :key "9", :value nil} {:process 44, :type :ok, :f :append, :key "2", :value "x 44 1 y"} {:process 44, :type :invoke, :f :append, :key "4", :value "x 44 2 y"} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 5 y"} {:process 0, :type :invoke, :f :append, :key "6", :value "x 0 6 y"} {:process 11, :type :ok, :f :append, :key "6", :value "x 11 4 y"} {:process 11, :type :invoke, :f :append, :key "6", :value "x 11 5 y"} {:process 3, :type :ok, :f :append, :key "3", :value "x 3 7 y"} {:process 3, :type :invoke, :f :get, :key "4", :value nil} {:process 3, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 yx 32 3 yx 5 3 yx 6 12 yx 3 5 yx 39 1 yx 44 0 y"} {:process 3, :type :invoke, :f :put, :key "1", :value "x 3 8 y"} {:process 44, :type :ok, :f :append, :key "4", :value "x 44 2 y"} {:process 44, :type :invoke, :f :append, :key "7", :value "x 44 3 y"} {:process 20, :type :ok, :f :append, :key "6", :value "x 20 6 y"} {:process 20, :type :invoke, :f :get, :key "8", :value nil} {:process 20, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 yx 1 0 yx 18 7 yx 23 0 yx 11 2 y"} {:process 20, :type :invoke, :f :get, :key "2", :value nil} {:process 42, :type :ok, :f :get, :key "9", :value "x 6 2 yx 13 0 yx 36 0 yx 3 0 yx 24 0 yx 49 2 yx 18 0 yx 18 1 yx 5 1 yx 21 0 yx 18 4 yx 18 6 yx 41 0 yx 8 2 yx 17 4 yx 20 5 yx 42 1 y"} {:process 42, :type :invoke, :f :get, :key "7", :value nil} {:process 0, :type :ok, :f :append, :key "6", :value "x 0 6 y"} {:process 0, :type :invoke, :f :get, :key "0", :value nil} {:process 42, :type :ok, :f :get, :key "7", :value "x 29 0 yx 17 0 yx 10 4 yx 1 1 yx 39 0 y"} {:process 42, :type :invoke, :f :append, :key "7", :value "x 42 2 y"} {:process 11, :type :ok, :f :append, :key "6", :value "x 11 5 y"} {:process 11, :type :invoke, :f :append, :key "2", :value "x 11 6 y"} {:process 3, :type :ok, :f :put, :key "1", :value "x 3 8 y"} {:process 3, :type :invoke, :f :get, :key "2", :value nil} {:process 46, :type :ok, :f :append, :key "5", :value "x 46 3 y"} {:process 11, :type :ok, :f :append, :key "2", :value "x 11 6 y"} {:process 11, :type :invoke, :f :append, :key "5", :value "x 11 7 y"} {:process 46, :type :invoke, :f :append, :key "0", :value "x 46 4 y"} {:process 0, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 yx 1 3 yx 2 3 yx 11 3 yx 40 1 yx 0 5 y"} {:process 0, :type :invoke, :f :get, :key "0", :value nil} {:process 44, :type :ok, :f :append, :key "7", :value "x 44 3 y"} {:process 44, :type :invoke, :f :get, :key "1", :value nil} {:process 0, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 yx 1 3 yx 2 3 yx 11 3 yx 40 1 yx 0 5 y"} {:process 0, :type :invoke, :f :append, :key "5", :value "x 0 7 y"} {:process 44, :type :ok, :f :get, :key "1", :value "x 3 8 y"} {:process 44, :type :invoke, :f :get, :key "9", :value nil} {:process 42, :type :ok, :f :append, :key "7", :value "x 42 2 y"} {:process 42, :type :invoke, :f :get, :key "0", :value nil} {:process 3, :type :ok, :f :get, :key "2", :value "x 0 2 yx 11 1 yx 47 0 yx 47 1 yx 21 5 yx 6 9 yx 41 2 yx 8 1 yx 6 13 yx 20 3 yx 44 1 yx 11 6 y"} {:process 3, :type :invoke, :f :put, :key "6", :value "x 3 9 y"} {:process 31, :type :ok, :f :append, :key "1", :value "x 31 3 y"} {:process 31, :type :invoke, :f :append, :key "3", :value "x 31 4 y"} {:process 0, :type :ok, :f :append, :key "5", :value "x 0 7 y"} {:process 0, :type :invoke, :f :get, :key "2", :value nil} {:process 42, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 yx 1 3 yx 2 3 yx 11 3 yx 40 1 yx 0 5 y"} {:process 42, :type :invoke, :f :get, :key "9", :value nil} {:process 31, :type :ok, :f :append, :key "3", :value "x 31 4 y"} {:process 31, :type :invoke, :f :append, :key "2", :value "x 31 5 y"} {:process 1, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 yx 1 3 yx 2 3 yx 11 3 yx 40 1 yx 0 5 y"} {:process 1, :type :invoke, :f :get, :key "8", :value nil} {:process 11, :type :ok, :f :append, :key "5", :value "x 11 7 y"} {:process 11, :type :invoke, :f :get, :key "7", :value nil} {:process 42, :type :ok, :f :get, :key "9", :value "x 6 2 yx 13 0 yx 36 0 yx 3 0 yx 24 0 yx 49 2 yx 18 0 yx 18 1 yx 5 1 yx 21 0 yx 18 4 yx 18 6 yx 41 0 yx 8 2 yx 17 4 yx 20 5 yx 42 1 y"} {:process 42, :type :invoke, :f :append, :key "4", :value "x 42 3 y"} {:process 46, :type :ok, :f :append, :key "0", :value "x 46 4 y"} {:process 46, :type :invoke, :f :get, :key "0", :value nil} {:process 1, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 yx 1 0 yx 18 7 yx 23 0 yx 11 2 y"} {:process 1, :type :invoke, :f :get, :key "7", :value nil} {:process 43, :type :ok, :f :put, :key "5", :value "x 43 0 y"} {:process 43, :type :invoke, :f :append, :key "7", :value "x 43 1 y"} {:process 46, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 yx 1 3 yx 2 3 yx 11 3 yx 40 1 yx 0 5 yx 46 4 y"} {:process 46, :type :invoke, :f :append, :key "4", :value "x 46 5 y"} {:process 26, :type :ok, :f :append, :key "0", :value "x 26 2 y"} {:process 26, :type :invoke, :f :get, :key "7", :value nil} {:process 11, :type :ok, :f :get, :key "7", :value "x 29 0 yx 17 0 yx 10 4 yx 1 1 yx 39 0 yx 44 3 yx 42 2 y"} {:process 11, :type :invoke, :f :get, :key "6", :value nil} {:process 42, :type :ok, :f :append, :key "4", :value "x 42 3 y"} {:process 42, :type :invoke, :f :get, :key "3", :value nil} {:process 24, :type :ok, :f :append, :key "7", :value "x 24 3 y"} {:process 24, :type :invoke, :f :get, :key "0", :value nil} {:process 31, :type :ok, :f :append, :key "2", :value "x 31 5 y"} {:process 31, :type :invoke, :f :put, :key "3", :value "x 31 6 y"} {:process 1, :type :ok, :f :get, :key "7", :value "x 29 0 yx 17 0 yx 10 4 yx 1 1 yx 39 0 yx 44 3 yx 42 2 y"} {:process 1, :type :invoke, :f :append, :key "5", :value "x 1 4 y"} {:process 24, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 yx 1 3 yx 2 3 yx 11 3 yx 40 1 yx 0 5 yx 46 4 yx 26 2 y"} {:process 24, :type :invoke, :f :append, :key "9", :value "x 24 4 y"} {:process 12, :type :ok, :f :append, :key "0", :value "x 12 7 y"} {:process 12, :type :invoke, :f :get, :key "3", :value nil} {:process 11, :type :ok, :f :get, :key "6", :value "x 3 9 y"} {:process 11, :type :invoke, :f :get, :key "8", :value nil} {:process 42, :type :ok, :f :get, :key "3", :value "x 17 1 yx 32 2 yx 20 1 yx 42 0 yx 3 7 yx 31 4 y"} {:process 42, :type :invoke, :f :get, :key "6", :value nil} {:process 46, :type :ok, :f :append, :key "4", :value "x 46 5 y"} {:process 46, :type :invoke, :f :get, :key "8", :value nil} {:process 30, :type :ok, :f :append, :key "8", :value "x 30 4 y"} {:process 30, :type :invoke, :f :append, :key "8", :value "x 30 5 y"} {:process 46, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 yx 1 0 yx 18 7 yx 23 0 yx 11 2 yx 30 4 y"} {:process 46, :type :invoke, :f :append, :key "2", :value "x 46 6 y"} {:process 24, :type :ok, :f :append, :key "9", :value "x 24 4 y"} {:process 24, :type :invoke, :f :append, :key "7", :value "x 24 5 y"} {:process 26, :type :ok, :f :get, :key "7", :value "x 29 0 yx 17 0 yx 10 4 yx 1 1 yx 39 0 yx 44 3 yx 42 2 yx 24 3 y"} {:process 26, :type :invoke, :f :get, :key "3", :value nil} {:process 43, :type :ok, :f :append, :key "7", :value "x 43 1 y"} {:process 43, :type :invoke, :f :put, :key "3", :value "x 43 2 y"} {:process 12, :type :ok, :f :get, :key "3", :value "x 17 1 yx 32 2 yx 20 1 yx 42 0 yx 3 7 yx 31 4 y"} {:process 12, :type :invoke, :f :append, :key "2", :value "x 12 8 y"} {:process 22, :type :ok, :f :append, :key "2", :value "x 22 0 y"} {:process 22, :type :invoke, :f :append, :key "6", :value "x 22 1 y"} {:process 24, :type :ok, :f :append, :key "7", :value "x 24 5 y"} {:process 24, :type :invoke, :f :get, :key "4", :value nil} {:process 11, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 yx 1 0 yx 18 7 yx 23 0 yx 11 2 yx 30 4 y"} {:process 11, :type :invoke, :f :append, :key "0", :value "x 11 8 y"} {:process 12, :type :ok, :f :append, :key "2", :value "x 12 8 y"} {:process 12, :type :invoke, :f :append, :key "2", :value "x 12 9 y"} {:process 26, :type :ok, :f :get, :key "3", :value "x 17 1 yx 32 2 yx 20 1 yx 42 0 yx 3 7 yx 31 4 y"} {:process 26, :type :invoke, :f :append, :key "3", :value "x 26 3 y"} {:process 24, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 yx 32 3 yx 5 3 yx 6 12 yx 3 5 yx 39 1 yx 44 0 yx 44 2 yx 42 3 yx 46 5 y"} {:process 24, :type :invoke, :f :get, :key "8", :value nil} {:process 20, :type :ok, :f :get, :key "2", :value "x 0 2 yx 11 1 yx 47 0 yx 47 1 yx 21 5 yx 6 9 yx 41 2 yx 8 1 yx 6 13 yx 20 3 yx 44 1 yx 11 6 yx 31 5 yx 22 0 yx 12 8 y"} {:process 20, :type :invoke, :f :append, :key "5", :value "x 20 7 y"} {:process 30, :type :ok, :f :append, :key "8", :value "x 30 5 y"} {:process 30, :type :invoke, :f :append, :key "4", :value "x 30 6 y"} {:process 22, :type :ok, :f :append, :key "6", :value "x 22 1 y"} {:process 22, :type :invoke, :f :get, :key "5", :value nil} {:process 43, :type :ok, :f :put, :key "3", :value "x 43 2 y"} {:process 43, :type :invoke, :f :append, :key "3", :value "x 43 3 y"} {:process 22, :type :ok, :f :get, :key "5", :value "x 43 0 yx 21 4 yx 6 8 yx 41 1 yx 32 1 yx 20 4 yx 46 3 yx 0 7 yx 11 7 y"} {:process 22, :type :invoke, :f :append, :key "8", :value "x 22 2 y"} {:process 24, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 yx 1 0 yx 18 7 yx 23 0 yx 11 2 yx 30 4 yx 30 5 y"} {:process 24, :type :invoke, :f :append, :key "3", :value "x 24 6 y"} {:process 11, :type :ok, :f :append, :key "0", :value "x 11 8 y"} {:process 11, :type :invoke, :f :append, :key "8", :value "x 11 9 y"} {:process 30, :type :ok, :f :append, :key "4", :value "x 30 6 y"} {:process 30, :type :invoke, :f :get, :key "1", :value nil} {:process 30, :type :ok, :f :get, :key "1", :value "x 3 8 yx 31 3 y"} {:process 30, :type :invoke, :f :append, :key "8", :value "x 30 7 y"} {:process 22, :type :ok, :f :append, :key "8", :value "x 22 2 y"} {:process 22, :type :invoke, :f :get, :key "6", :value nil} {:process 0, :type :ok, :f :get, :key "2", :value "x 0 2 yx 11 1 y"} {:process 0, :type :invoke, :f :get, :key "1", :value nil} {:process 22, :type :ok, :f :get, :key "6", :value "x 3 9 yx 22 1 y"} {:process 22, :type :invoke, :f :get, :key "4", :value nil} {:process 24, :type :ok, :f :append, :key "3", :value "x 24 6 y"} {:process 24, :type :invoke, :f :append, :key "2", :value "x 24 7 y"} {:process 26, :type :ok, :f :append, :key "3", :value "x 26 3 y"} {:process 26, :type :invoke, :f :get, :key "5", :value nil} {:process 26, :type :ok, :f :get, :key "5", :value "x 43 0 yx 21 4 yx 6 8 yx 41 1 yx 32 1 yx 20 4 yx 46 3 yx 0 7 yx 11 7 y"} {:process 26, :type :invoke, :f :append, :key "4", :value "x 26 4 y"} {:process 0, :type :ok, :f :get, :key "1", :value "x 30 0 yx 46 1 yx 30 3 yx 13 1 yx 5 0 yx 15 4 yx 34 0 yx 25 0 yx 18 3 y"} {:process 0, :type :invoke, :f :append, :key "8", :value "x 0 8 y"} {:process 27, :type :ok, :f :append, :key "8", :value "x 27 3 y"} {:process 27, :type :invoke, :f :get, :key "0", :value nil} {:process 39, :type :ok, :f :get, :key "3", :value "x 43 2 y"} {:process 39, :type :invoke, :f :append, :key "8", :value "x 39 3 y"} {:process 30, :type :ok, :f :append, :key "8", :value "x 30 7 y"} {:process 30, :type :invoke, :f :put, :key "7", :value "x 30 8 y"} {:process 44, :type :ok, :f :get, :key "9", :value "x 6 2 yx 13 0 yx 36 0 yx 3 0 yx 24 0 yx 49 2 yx 18 0 yx 18 1 yx 5 1 yx 21 0 yx 18 4 yx 18 6 yx 41 0 yx 8 2 yx 17 4 yx 20 5 yx 42 1 yx 24 4 y"} {:process 44, :type :invoke, :f :put, :key "0", :value "x 44 4 y"} {:process 27, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 yx 1 3 yx 2 3 yx 11 3 yx 40 1 yx 0 5 yx 46 4 yx 26 2 yx 12 7 yx 11 8 y"} {:process 27, :type :invoke, :f :get, :key "4", :value nil} {:process 11, :type :ok, :f :append, :key "8", :value "x 11 9 y"} {:process 11, :type :invoke, :f :append, :key "3", :value "x 11 10 y"} {:process 13, :type :ok, :f :append, :key "5", :value "x 13 5 y"} {:process 13, :type :invoke, :f :get, :key "5", :value nil} {:process 22, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 yx 32 3 yx 5 3 yx 6 12 yx 3 5 yx 39 1 yx 44 0 yx 44 2 yx 42 3 yx 46 5 yx 30 6 y"} {:process 22, :type :invoke, :f :get, :key "9", :value nil} {:process 36, :type :ok, :f :append, :key "0", :value "x 36 1 y"} {:process 36, :type :invoke, :f :get, :key "0", :value nil} {:process 13, :type :ok, :f :get, :key "5", :value "x 43 0 yx 21 4 yx 6 8 yx 41 1 yx 32 1 yx 20 4 yx 46 3 yx 0 7 yx 11 7 yx 13 5 y"} {:process 13, :type :invoke, :f :get, :key "5", :value nil} {:process 26, :type :ok, :f :append, :key "4", :value "x 26 4 y"} {:process 26, :type :invoke, :f :get, :key "5", :value nil} {:process 45, :type :ok, :f :append, :key "5", :value "x 45 0 y"} {:process 45, :type :invoke, :f :append, :key "0", :value "x 45 1 y"} {:process 36, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 yx 1 3 yx 2 3 yx 11 3 yx 40 1 yx 0 5 yx 46 4 yx 26 2 yx 12 7 yx 11 8 yx 36 1 y"} {:process 36, :type :invoke, :f :get, :key "6", :value nil} {:process 36, :type :ok, :f :get, :key "6", :value "x 3 9 yx 22 1 y"} {:process 36, :type :invoke, :f :get, :key "6", :value nil} {:process 30, :type :ok, :f :put, :key "7", :value "x 30 8 y"} {:process 30, :type :invoke, :f :append, :key "3", :value "x 30 9 y"} {:process 11, :type :ok, :f :append, :key "3", :value "x 11 10 y"} {:process 11, :type :invoke, :f :append, :key "8", :value "x 11 11 y"} {:process 26, :type :ok, :f :get, :key "5", :value "x 43 0 yx 21 4 yx 6 8 yx 41 1 yx 32 1 yx 20 4 yx 46 3 yx 0 7 yx 11 7 yx 13 5 yx 45 0 y"} {:process 26, :type :invoke, :f :get, :key "6", :value nil} {:process 45, :type :ok, :f :append, :key "0", :value "x 45 1 y"} {:process 45, :type :invoke, :f :get, :key "3", :value nil} {:process 26, :type :ok, :f :get, :key "6", :value "x 3 9 yx 22 1 y"} {:process 26, :type :invoke, :f :get, :key "4", :value nil} {:process 15, :type :ok, :f :append, :key "5", :value "x 15 9 y"} {:process 15, :type :invoke, :f :get, :key "5", :value nil} {:process 15, :type :ok, :f :get, :key "5", :value "x 43 0 yx 21 4 yx 6 8 yx 41 1 yx 32 1 yx 20 4 yx 46 3 yx 0 7 yx 11 7 yx 13 5 yx 45 0 yx 15 9 y"} {:process 15, :type :invoke, :f :get, :key "1", :value nil} {:process 26, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 yx 32 3 yx 5 3 yx 6 12 yx 3 5 yx 39 1 yx 44 0 yx 44 2 yx 42 3 yx 46 5 yx 30 6 yx 26 4 y"} {:process 26, :type :invoke, :f :append, :key "6", :value "x 26 5 y"} {:process 30, :type :ok, :f :append, :key "3", :value "x 30 9 y"} {:process 30, :type :invoke, :f :append, :key "3", :value "x 30 10 y"} {:process 11, :type :ok, :f :append, :key "8", :value "x 11 11 y"} {:process 11, :type :invoke, :f :append, :key "2", :value "x 11 12 y"} {:process 15, :type :ok, :f :get, :key "1", :value "x 3 8 yx 31 3 y"} {:process 15, :type :invoke, :f :append, :key "6", :value "x 15 10 y"} {:process 45, :type :ok, :f :get, :key "3", :value "x 43 2 yx 26 3 yx 24 6 yx 11 10 yx 30 9 y"} {:process 45, :type :invoke, :f :get, :key "7", :value nil} {:process 26, :type :ok, :f :append, :key "6", :value "x 26 5 y"} {:process 26, :type :invoke, :f :append, :key "2", :value "x 26 6 y"} {:process 11, :type :ok, :f :append, :key "2", :value "x 11 12 y"} {:process 11, :type :invoke, :f :append, :key "5", :value "x 11 13 y"} {:process 45, :type :ok, :f :get, :key "7", :value "x 30 8 y"} {:process 45, :type :invoke, :f :get, :key "1", :value nil} {:process 45, :type :ok, :f :get, :key "1", :value "x 3 8 yx 31 3 y"} {:process 45, :type :invoke, :f :put, :key "2", :value "x 45 2 y"} {:process 15, :type :ok, :f :append, :key "6", :value "x 15 10 y"} {:process 15, :type :invoke, :f :append, :key "8", :value "x 15 11 y"} {:process 30, :type :ok, :f :append, :key "3", :value "x 30 10 y"} {:process 30, :type :invoke, :f :get, :key "3", :value nil} {:process 11, :type :ok, :f :append, :key "5", :value "x 11 13 y"} {:process 11, :type :invoke, :f :get, :key "0", :value nil} {:process 11, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 yx 1 3 yx 2 3 yx 11 3 yx 40 1 yx 0 5 yx 46 4 yx 26 2 yx 12 7 yx 11 8 yx 36 1 yx 45 1 y"} {:process 11, :type :invoke, :f :get, :key "8", :value nil} {:process 30, :type :ok, :f :get, :key "3", :value "x 43 2 yx 26 3 yx 24 6 yx 11 10 yx 30 9 yx 30 10 y"} {:process 30, :type :invoke, :f :append, :key "4", :value "x 30 11 y"} {:process 11, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 yx 1 0 yx 18 7 yx 23 0 yx 11 2 yx 30 4 yx 30 5 yx 22 2 yx 27 3 yx 30 7 yx 11 9 yx 11 11 y"} {:process 11, :type :invoke, :f :get, :key "8", :value nil} {:process 26, :type :ok, :f :append, :key "2", :value "x 26 6 y"} {:process 26, :type :invoke, :f :get, :key "1", :value nil} {:process 11, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 yx 1 0 yx 18 7 yx 23 0 yx 11 2 yx 30 4 yx 30 5 yx 22 2 yx 27 3 yx 30 7 yx 11 9 yx 11 11 y"} {:process 11, :type :invoke, :f :get, :key "1", :value nil} {:process 26, :type :ok, :f :get, :key "1", :value "x 3 8 yx 31 3 y"} {:process 26, :type :invoke, :f :get, :key "6", :value nil} {:process 15, :type :ok, :f :append, :key "8", :value "x 15 11 y"} {:process 15, :type :invoke, :f :get, :key "8", :value nil} {:process 11, :type :ok, :f :get, :key "1", :value "x 3 8 yx 31 3 y"} {:process 11, :type :invoke, :f :append, :key "9", :value "x 11 14 y"} {:process 16, :type :ok, :f :append, :key "4", :value "x 16 1 y"} {:process 16, :type :invoke, :f :append, :key "6", :value "x 16 2 y"} {:process 14, :type :ok, :f :put, :key "6", :value "x 14 0 y"} {:process 14, :type :invoke, :f :get, :key "1", :value nil} {:process 15, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 yx 1 0 yx 18 7 yx 23 0 yx 11 2 yx 30 4 yx 30 5 yx 22 2 yx 27 3 yx 30 7 yx 11 9 yx 11 11 yx 15 11 y"} {:process 15, :type :invoke, :f :get, :key "1", :value nil} {:process 30, :type :ok, :f :append, :key "4", :value "x 30 11 y"} {:process 30, :type :invoke, :f :append, :key "8", :value "x 30 12 y"} {:process 16, :type :ok, :f :append, :key "6", :value "x 16 2 y"} {:process 16, :type :invoke, :f :put, :key "7", :value "x 16 3 y"} {:process 27, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 yx 32 3 yx 5 3 yx 6 12 yx 3 5 yx 39 1 yx 44 0 yx 44 2 yx 42 3 yx 46 5 yx 30 6 yx 26 4 yx 30 11 y"} {:process 27, :type :invoke, :f :append, :key "7", :value "x 27 4 y"} {:process 26, :type :ok, :f :get, :key "6", :value "x 3 9 yx 22 1 yx 26 5 yx 15 10 yx 16 2 y"} {:process 26, :type :invoke, :f :append, :key "2", :value "x 26 7 y"} {:process 30, :type :ok, :f :append, :key "8", :value "x 30 12 y"} {:process 30, :type :invoke, :f :get, :key "5", :value nil} {:process 14, :type :ok, :f :get, :key "1", :value "x 3 8 yx 31 3 y"} {:process 14, :type :invoke, :f :put, :key "2", :value "x 14 1 y"} {:process 36, :type :ok, :f :get, :key "6", :value "x 3 9 yx 22 1 yx 26 5 yx 15 10 yx 16 2 y"} {:process 36, :type :invoke, :f :get, :key "4", :value nil} {:process 11, :type :ok, :f :append, :key "9", :value "x 11 14 y"} {:process 11, :type :invoke, :f :append, :key "9", :value "x 11 15 y"} {:process 30, :type :ok, :f :get, :key "5", :value "x 43 0 yx 21 4 yx 6 8 yx 41 1 yx 32 1 yx 20 4 yx 46 3 yx 0 7 yx 11 7 yx 13 5 yx 45 0 yx 15 9 yx 11 13 y"} {:process 30, :type :invoke, :f :get, :key "8", :value nil} {:process 30, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 yx 1 0 yx 18 7 yx 23 0 yx 11 2 yx 30 4 yx 30 5 yx 22 2 yx 27 3 yx 30 7 yx 11 9 yx 11 11 yx 15 11 yx 30 12 y"} {:process 30, :type :invoke, :f :append, :key "2", :value "x 30 13 y"} {:process 26, :type :ok, :f :append, :key "2", :value "x 26 7 y"} {:process 26, :type :invoke, :f :get, :key "4", :value nil} {:process 26, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 yx 32 3 yx 5 3 yx 6 12 yx 3 5 yx 39 1 yx 44 0 yx 44 2 yx 42 3 yx 46 5 yx 30 6 yx 26 4 yx 30 11 y"} {:process 26, :type :invoke, :f :get, :key "7", :value nil} {:process 16, :type :ok, :f :put, :key "7", :value "x 16 3 y"} {:process 16, :type :invoke, :f :append, :key "2", :value "x 16 4 y"} {:process 42, :type :ok, :f :get, :key "6", :value "x 14 0 yx 11 0 yx 31 0 y"} {:process 42, :type :invoke, :f :append, :key "4", :value "x 42 4 y"} {:process 14, :type :ok, :f :put, :key "2", :value "x 14 1 y"} {:process 14, :type :invoke, :f :get, :key "1", :value nil} {:process 26, :type :ok, :f :get, :key "7", :value "x 16 3 y"} {:process 26, :type :invoke, :f :get, :key "4", :value nil} {:process 16, :type :ok, :f :append, :key "2", :value "x 16 4 y"} {:process 16, :type :invoke, :f :append, :key "1", :value "x 16 5 y"} {:process 11, :type :ok, :f :append, :key "9", :value "x 11 15 y"} {:process 11, :type :invoke, :f :append, :key "3", :value "x 11 16 y"} {:process 30, :type :ok, :f :append, :key "2", :value "x 30 13 y"} {:process 30, :type :invoke, :f :append, :key "3", :value "x 30 14 y"} {:process 26, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 yx 32 3 yx 5 3 yx 6 12 yx 3 5 yx 39 1 yx 44 0 yx 44 2 yx 42 3 yx 46 5 yx 30 6 yx 26 4 yx 30 11 y"} {:process 26, :type :invoke, :f :get, :key "7", :value nil} {:process 26, :type :ok, :f :get, :key "7", :value "x 16 3 y"} {:process 26, :type :invoke, :f :get, :key "2", :value nil} {:process 7, :type :ok, :f :append, :key "4", :value "x 7 1 y"} {:process 7, :type :invoke, :f :get, :key "8", :value nil} {:process 25, :type :ok, :f :append, :key "1", :value "x 25 0 y"} {:process 25, :type :invoke, :f :put, :key "0", :value "x 25 1 y"} {:process 26, :type :ok, :f :get, :key "2", :value "x 14 1 yx 16 4 yx 30 13 y"} {:process 26, :type :invoke, :f :append, :key "1", :value "x 26 8 y"} {:process 16, :type :ok, :f :append, :key "1", :value "x 16 5 y"} {:process 16, :type :invoke, :f :append, :key "0", :value "x 16 6 y"} {:process 48, :type :ok, :f :append, :key "1", :value "x 48 2 y"} {:process 48, :type :invoke, :f :append, :key "8", :value "x 48 3 y"} {:process 7, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 yx 1 0 yx 18 7 yx 23 0 yx 11 2 yx 30 4 yx 30 5 yx 22 2 yx 27 3 yx 30 7 yx 11 9 yx 11 11 yx 15 11 yx 30 12 y"} {:process 7, :type :invoke, :f :append, :key "8", :value "x 7 2 y"} {:process 16, :type :ok, :f :append, :key "0", :value "x 16 6 y"} {:process 16, :type :invoke, :f :append, :key "0", :value "x 16 7 y"} {:process 30, :type :ok, :f :append, :key "3", :value "x 30 14 y"} {:process 30, :type :invoke, :f :get, :key "3", :value nil} {:process 48, :type :ok, :f :append, :key "8", :value "x 48 3 y"} {:process 48, :type :invoke, :f :get, :key "5", :value nil} {:process 16, :type :ok, :f :append, :key "0", :value "x 16 7 y"} {:process 16, :type :invoke, :f :get, :key "4", :value nil} {:process 26, :type :ok, :f :append, :key "1", :value "x 26 8 y"} {:process 26, :type :invoke, :f :get, :key "8", :value nil} {:process 22, :type :ok, :f :get, :key "9", :value "x 6 2 yx 13 0 yx 36 0 yx 3 0 yx 24 0 yx 49 2 yx 18 0 yx 18 1 yx 5 1 yx 21 0 yx 18 4 yx 18 6 yx 41 0 yx 8 2 yx 17 4 yx 20 5 yx 42 1 yx 24 4 yx 11 14 yx 11 15 y"} {:process 22, :type :invoke, :f :append, :key "6", :value "x 22 3 y"} {:process 26, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 yx 1 0 yx 18 7 yx 23 0 yx 11 2 yx 30 4 yx 30 5 yx 22 2 yx 27 3 yx 30 7 yx 11 9 yx 11 11 yx 15 11 yx 30 12 yx 48 3 y"} {:process 26, :type :invoke, :f :append, :key "6", :value "x 26 9 y"} {:process 15, :type :ok, :f :get, :key "1", :value "x 3 8 yx 31 3 yx 16 5 yx 48 2 y"} {:process 15, :type :invoke, :f :append, :key "0", :value "x 15 12 y"} {:process 13, :type :ok, :f :get, :key "5", :value "x 43 0 yx 21 4 yx 6 8 yx 41 1 yx 32 1 yx 20 4 yx 46 3 yx 0 7 yx 11 7 yx 13 5 yx 45 0 yx 15 9 yx 11 13 y"} {:process 13, :type :invoke, :f :append, :key "1", :value "x 13 6 y"} {:process 48, :type :ok, :f :get, :key "5", :value "x 43 0 yx 21 4 yx 6 8 yx 41 1 yx 32 1 yx 20 4 yx 46 3 yx 0 7 yx 11 7 yx 13 5 yx 45 0 yx 15 9 yx 11 13 y"} {:process 48, :type :invoke, :f :get, :key "8", :value nil} {:process 30, :type :ok, :f :get, :key "3", :value "x 37 5 y"} {:process 30, :type :invoke, :f :get, :key "4", :value nil} {:process 30, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 yx 32 3 yx 5 3 yx 6 12 yx 3 5 yx 39 1 yx 44 0 yx 44 2 yx 42 3 yx 46 5 yx 30 6 yx 26 4 yx 30 11 yx 7 1 y"} {:process 30, :type :invoke, :f :put, :key "8", :value "x 30 15 y"} {:process 48, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 yx 1 0 yx 18 7 yx 23 0 yx 11 2 yx 30 4 yx 30 5 yx 22 2 yx 27 3 yx 30 7 yx 11 9 yx 11 11 yx 15 11 yx 30 12 yx 48 3 y"} {:process 48, :type :invoke, :f :get, :key "2", :value nil} {:process 7, :type :ok, :f :append, :key "8", :value "x 7 2 y"} {:process 7, :type :invoke, :f :get, :key "8", :value nil} {:process 7, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 yx 1 0 yx 18 7 yx 23 0 yx 11 2 yx 30 4 yx 30 5 yx 22 2 yx 27 3 yx 30 7 yx 11 9 yx 11 11 yx 15 11 yx 30 12 yx 48 3 yx 7 2 y"} {:process 7, :type :invoke, :f :get, :key "2", :value nil} {:process 30, :type :ok, :f :put, :key "8", :value "x 30 15 y"} {:process 30, :type :invoke, :f :append, :key "1", :value "x 30 16 y"} {:process 26, :type :ok, :f :append, :key "6", :value "x 26 9 y"} {:process 26, :type :invoke, :f :append, :key "6", :value "x 26 10 y"} {:process 48, :type :ok, :f :get, :key "2", :value "x 14 1 yx 16 4 yx 30 13 y"} {:process 48, :type :invoke, :f :get, :key "1", :value nil} {:process 14, :type :ok, :f :get, :key "1", :value "x 30 0 yx 46 1 yx 30 3 yx 13 1 yx 5 0 yx 15 4 yx 34 0 yx 25 0 yx 18 3 y"} {:process 14, :type :invoke, :f :append, :key "5", :value "x 14 2 y"} {:process 7, :type :ok, :f :get, :key "2", :value "x 14 1 yx 16 4 yx 30 13 y"} {:process 7, :type :invoke, :f :append, :key "4", :value "x 7 3 y"} {:process 7, :type :ok, :f :append, :key "4", :value "x 7 3 y"} {:process 7, :type :invoke, :f :get, :key "1", :value nil} {:process 48, :type :ok, :f :get, :key "1", :value "x 3 8 yx 31 3 yx 16 5 yx 48 2 yx 26 8 y"} {:process 48, :type :invoke, :f :append, :key "3", :value "x 48 4 y"} {:process 30, :type :ok, :f :append, :key "1", :value "x 30 16 y"} {:process 30, :type :invoke, :f :get, :key "0", :value nil} {:process 30, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 yx 1 3 yx 2 3 yx 11 3 yx 40 1 yx 0 5 yx 46 4 yx 26 2 yx 12 7 yx 11 8 yx 36 1 yx 45 1 yx 16 6 yx 16 7 y"} {:process 30, :type :invoke, :f :append, :key "8", :value "x 30 17 y"} {:process 26, :type :ok, :f :append, :key "6", :value "x 26 10 y"} {:process 26, :type :invoke, :f :get, :key "4", :value nil} {:process 48, :type :ok, :f :append, :key "3", :value "x 48 4 y"} {:process 48, :type :invoke, :f :get, :key "3", :value nil} {:process 26, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 yx 32 3 yx 5 3 yx 6 12 yx 3 5 yx 39 1 yx 44 0 yx 44 2 yx 42 3 yx 46 5 yx 30 6 yx 26 4 yx 30 11 yx 7 1 yx 7 3 y"} {:process 26, :type :invoke, :f :append, :key "4", :value "x 26 11 y"} {:process 30, :type :ok, :f :append, :key "8", :value "x 30 17 y"} {:process 30, :type :invoke, :f :append, :key "6", :value "x 30 18 y"} {:process 16, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 yx 32 3 yx 5 3 yx 6 12 yx 3 5 yx 39 1 yx 44 0 yx 44 2 yx 42 3 yx 46 5 yx 30 6 yx 26 4 yx 30 11 yx 7 1 yx 7 3 y"} {:process 16, :type :invoke, :f :get, :key "2", :value nil} {:process 48, :type :ok, :f :get, :key "3", :value "x 37 5 yx 48 4 y"} {:process 48, :type :invoke, :f :get, :key "0", :value nil} {:process 16, :type :ok, :f :get, :key "2", :value "x 14 1 yx 16 4 yx 30 13 y"} {:process 16, :type :invoke, :f :append, :key "5", :value "x 16 8 y"} {:process 48, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 yx 1 3 yx 2 3 yx 11 3 yx 40 1 yx 0 5 yx 46 4 yx 26 2 yx 12 7 yx 11 8 yx 36 1 yx 45 1 yx 16 6 yx 16 7 y"} {:process 48, :type :invoke, :f :get, :key "2", :value nil} {:process 36, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 y"} {:process 36, :type :invoke, :f :append, :key "0", :value "x 36 2 y"} {:process 48, :type :ok, :f :get, :key "2", :value "x 14 1 yx 16 4 yx 30 13 y"} {:process 48, :type :invoke, :f :append, :key "2", :value "x 48 5 y"} {:process 7, :type :ok, :f :get, :key "1", :value "x 3 8 yx 31 3 yx 16 5 yx 48 2 yx 26 8 yx 30 16 y"} {:process 7, :type :invoke, :f :get, :key "8", :value nil} {:process 7, :type :ok, :f :get, :key "8", :value "x 30 15 yx 30 17 y"} {:process 7, :type :invoke, :f :append, :key "5", :value "x 7 4 y"} {:process 34, :type :ok, :f :append, :key "3", :value "x 34 2 y"} {:process 34, :type :invoke, :f :append, :key "8", :value "x 34 3 y"} {:process 4, :type :ok, :f :append, :key "2", :value "x 4 2 y"} {:process 4, :type :invoke, :f :append, :key "7", :value "x 4 3 y"} {:process 47, :type :ok, :f :put, :key "8", :value "x 47 5 y"} {:process 47, :type :invoke, :f :get, :key "1", :value nil} {:process 47, :type :ok, :f :get, :key "1", :value "x 3 8 yx 31 3 yx 16 5 yx 48 2 yx 26 8 yx 30 16 y"} {:process 47, :type :invoke, :f :get, :key "9", :value nil} {:process 21, :type :ok, :f :append, :key "5", :value "x 21 7 y"} {:process 21, :type :invoke, :f :get, :key "1", :value nil} {:process 49, :type :ok, :f :append, :key "2", :value "x 49 8 y"} {:process 49, :type :invoke, :f :get, :key "1", :value nil} {:process 49, :type :ok, :f :get, :key "1", :value "x 3 8 yx 31 3 yx 16 5 yx 48 2 yx 26 8 yx 30 16 y"} {:process 49, :type :invoke, :f :get, :key "6", :value nil} {:process 33, :type :ok, :f :append, :key "9", :value "x 33 2 y"} {:process 33, :type :invoke, :f :get, :key "5", :value nil} {:process 4, :type :ok, :f :append, :key "7", :value "x 4 3 y"} {:process 4, :type :invoke, :f :append, :key "5", :value "x 4 4 y"} {:process 41, :type :ok, :f :append, :key "6", :value "x 41 3 y"} {:process 41, :type :invoke, :f :get, :key "2", :value nil} {:process 21, :type :ok, :f :get, :key "1", :value "x 3 8 yx 31 3 yx 16 5 yx 48 2 yx 26 8 yx 30 16 y"} {:process 21, :type :invoke, :f :get, :key "6", :value nil} {:process 21, :type :ok, :f :get, :key "6", :value "x 3 9 yx 22 1 yx 26 5 yx 15 10 yx 16 2 yx 26 9 yx 26 10 yx 30 18 yx 41 3 y"} {:process 21, :type :invoke, :f :get, :key "1", :value nil} {:process 29, :type :ok, :f :append, :key "3", :value "x 29 2 y"} {:process 29, :type :invoke, :f :get, :key "1", :value nil} {:process 49, :type :ok, :f :get, :key "6", :value "x 3 9 yx 22 1 yx 26 5 yx 15 10 yx 16 2 yx 26 9 yx 26 10 yx 30 18 yx 41 3 y"} {:process 49, :type :invoke, :f :append, :key "4", :value "x 49 9 y"} {:process 10, :type :ok, :f :append, :key "7", :value "x 10 4 y"} {:process 10, :type :invoke, :f :append, :key "8", :value "x 10 5 y"} {:process 29, :type :ok, :f :get, :key "1", :value "x 3 8 yx 31 3 yx 16 5 yx 48 2 yx 26 8 yx 30 16 y"} {:process 29, :type :invoke, :f :append, :key "6", :value "x 29 3 y"} {:process 4, :type :ok, :f :append, :key "5", :value "x 4 4 y"} {:process 4, :type :invoke, :f :append, :key "0", :value "x 4 5 y"} {:process 49, :type :ok, :f :append, :key "4", :value "x 49 9 y"} {:process 49, :type :invoke, :f :get, :key "1", :value nil} {:process 49, :type :ok, :f :get, :key "1", :value "x 3 8 yx 31 3 yx 16 5 yx 48 2 yx 26 8 yx 30 16 y"} {:process 49, :type :invoke, :f :get, :key "6", :value nil} {:process 10, :type :ok, :f :append, :key "8", :value "x 10 5 y"} {:process 10, :type :invoke, :f :append, :key "2", :value "x 10 6 y"} {:process 49, :type :ok, :f :get, :key "6", :value "x 3 9 yx 22 1 yx 26 5 yx 15 10 yx 16 2 yx 26 9 yx 26 10 yx 30 18 yx 41 3 y"} {:process 49, :type :invoke, :f :append, :key "5", :value "x 49 10 y"} {:process 8, :type :ok, :f :append, :key "0", :value "x 8 3 y"} {:process 8, :type :invoke, :f :append, :key "5", :value "x 8 4 y"} {:process 29, :type :ok, :f :append, :key "6", :value "x 29 3 y"} {:process 29, :type :invoke, :f :get, :key "5", :value nil} {:process 4, :type :ok, :f :append, :key "0", :value "x 4 5 y"} {:process 4, :type :invoke, :f :get, :key "5", :value nil} {:process 29, :type :ok, :f :get, :key "5", :value "x 43 0 yx 21 4 yx 6 8 yx 41 1 yx 32 1 yx 20 4 yx 46 3 yx 0 7 yx 11 7 yx 13 5 yx 45 0 yx 15 9 yx 11 13 yx 21 7 yx 4 4 y"} {:process 29, :type :invoke, :f :append, :key "3", :value "x 29 4 y"} {:process 49, :type :ok, :f :append, :key "5", :value "x 49 10 y"} {:process 32, :type :ok, :f :append, :key "4", :value "x 32 4 y"} {:process 32, :type :invoke, :f :append, :key "0", :value "x 32 5 y"} {:process 49, :type :invoke, :f :put, :key "7", :value "x 49 11 y"} {:process 10, :type :ok, :f :append, :key "2", :value "x 10 6 y"} {:process 10, :type :invoke, :f :put, :key "3", :value "x 10 7 y"} {:process 4, :type :ok, :f :get, :key "5", :value "x 43 0 yx 21 4 yx 6 8 yx 41 1 yx 32 1 yx 20 4 yx 46 3 yx 0 7 yx 11 7 yx 13 5 yx 45 0 yx 15 9 yx 11 13 yx 21 7 yx 4 4 yx 49 10 y"} {:process 4, :type :invoke, :f :get, :key "1", :value nil} {:process 4, :type :ok, :f :get, :key "1", :value "x 3 8 yx 31 3 yx 16 5 yx 48 2 yx 26 8 yx 30 16 y"} {:process 4, :type :invoke, :f :get, :key "7", :value nil} {:process 18, :type :ok, :f :append, :key "8", :value "x 18 7 y"} {:process 18, :type :invoke, :f :get, :key "7", :value nil} {:process 47, :type :ok, :f :get, :key "9", :value "x 6 2 yx 13 0 yx 36 0 yx 3 0 yx 24 0 yx 49 2 yx 18 0 yx 18 1 yx 5 1 yx 21 0 yx 18 4 yx 18 6 yx 41 0 yx 8 2 yx 17 4 yx 20 5 yx 42 1 yx 24 4 yx 11 14 yx 11 15 y"} {:process 47, :type :invoke, :f :append, :key "3", :value "x 47 6 y"} {:process 18, :type :ok, :f :get, :key "7", :value "x 16 3 yx 4 3 y"} {:process 18, :type :invoke, :f :append, :key "8", :value "x 18 8 y"} {:process 5, :type :ok, :f :append, :key "4", :value "x 5 3 y"} {:process 49, :type :ok, :f :put, :key "7", :value "x 49 11 y"} {:process 5, :type :invoke, :f :append, :key "1", :value "x 5 4 y"} {:process 49, :type :invoke, :f :get, :key "0", :value nil} {:process 17, :type :ok, :f :append, :key "3", :value "x 17 5 y"} {:process 29, :type :ok, :f :append, :key "3", :value "x 29 4 y"} {:process 29, :type :invoke, :f :append, :key "3", :value "x 29 5 y"} {:process 17, :type :invoke, :f :get, :key "4", :value nil} {:process 8, :type :ok, :f :append, :key "5", :value "x 8 4 y"} {:process 8, :type :invoke, :f :append, :key "6", :value "x 8 5 y"} {:process 23, :type :ok, :f :append, :key "6", :value "x 23 1 y"} {:process 23, :type :invoke, :f :get, :key "0", :value nil} {:process 17, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 yx 32 3 yx 5 3 yx 6 12 yx 3 5 yx 39 1 yx 44 0 yx 44 2 yx 42 3 yx 46 5 yx 30 6 yx 26 4 yx 30 11 yx 7 1 yx 7 3 yx 26 11 yx 49 9 yx 32 4 y"} {:process 17, :type :invoke, :f :append, :key "4", :value "x 17 6 y"} {:process 10, :type :ok, :f :put, :key "3", :value "x 10 7 y"} {:process 10, :type :invoke, :f :append, :key "6", :value "x 10 8 y"} {:process 5, :type :ok, :f :append, :key "1", :value "x 5 4 y"} {:process 5, :type :invoke, :f :get, :key "9", :value nil} {:process 49, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 yx 1 3 yx 2 3 yx 11 3 yx 40 1 yx 0 5 yx 46 4 yx 26 2 yx 12 7 yx 11 8 yx 36 1 yx 45 1 yx 16 6 yx 16 7 yx 8 3 yx 4 5 y"} {:process 49, :type :invoke, :f :append, :key "6", :value "x 49 12 y"} {:process 5, :type :ok, :f :get, :key "9", :value "x 6 2 yx 13 0 yx 36 0 yx 3 0 yx 24 0 yx 49 2 yx 18 0 yx 18 1 yx 5 1 yx 21 0 yx 18 4 yx 18 6 yx 41 0 yx 8 2 yx 17 4 yx 20 5 yx 42 1 yx 24 4 yx 11 14 yx 11 15 yx 33 2 y"} {:process 5, :type :invoke, :f :append, :key "7", :value "x 5 5 y"} {:process 41, :type :ok, :f :get, :key "2", :value "x 14 1 yx 16 4 yx 30 13 y"} {:process 41, :type :invoke, :f :append, :key "5", :value "x 41 4 y"} {:process 29, :type :ok, :f :append, :key "3", :value "x 29 5 y"} {:process 29, :type :invoke, :f :append, :key "9", :value "x 29 6 y"} {:process 21, :type :ok, :f :get, :key "1", :value "x 3 8 yx 31 3 yx 16 5 yx 48 2 yx 26 8 yx 30 16 y"} {:process 21, :type :invoke, :f :get, :key "0", :value nil} {:process 33, :type :ok, :f :get, :key "5", :value "x 43 0 yx 21 4 yx 6 8 yx 41 1 yx 32 1 yx 20 4 yx 46 3 yx 0 7 yx 11 7 yx 13 5 yx 45 0 yx 15 9 yx 11 13 y"} {:process 33, :type :invoke, :f :append, :key "9", :value "x 33 3 y"} {:process 6, :type :ok, :f :append, :key "7", :value "x 6 14 y"} {:process 6, :type :invoke, :f :put, :key "1", :value "x 6 15 y"} {:process 8, :type :ok, :f :append, :key "6", :value "x 8 5 y"} {:process 8, :type :invoke, :f :append, :key "5", :value "x 8 6 y"} {:process 23, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 yx 1 3 yx 2 3 yx 11 3 yx 40 1 yx 0 5 yx 46 4 yx 26 2 yx 12 7 yx 11 8 yx 36 1 yx 45 1 yx 16 6 yx 16 7 yx 8 3 yx 4 5 y"} {:process 23, :type :invoke, :f :append, :key "1", :value "x 23 2 y"} {:process 10, :type :ok, :f :append, :key "6", :value "x 10 8 y"} {:process 10, :type :invoke, :f :get, :key "4", :value nil} {:process 18, :type :ok, :f :append, :key "8", :value "x 18 8 y"} {:process 18, :type :invoke, :f :get, :key "9", :value nil} {:process 49, :type :ok, :f :append, :key "6", :value "x 49 12 y"} {:process 17, :type :ok, :f :append, :key "4", :value "x 17 6 y"} {:process 5, :type :ok, :f :append, :key "7", :value "x 5 5 y"} {:process 17, :type :invoke, :f :append, :key "7", :value "x 17 7 y"} {:process 49, :type :invoke, :f :put, :key "6", :value "x 49 13 y"} {:process 5, :type :invoke, :f :get, :key "8", :value nil} {:process 5, :type :ok, :f :get, :key "8", :value "x 47 5 yx 10 5 yx 18 8 y"} {:process 5, :type :invoke, :f :get, :key "6", :value nil} {:process 23, :type :ok, :f :append, :key "1", :value "x 23 2 y"} {:process 23, :type :invoke, :f :get, :key "6", :value nil} {:process 8, :type :ok, :f :append, :key "5", :value "x 8 6 y"} {:process 8, :type :invoke, :f :append, :key "7", :value "x 8 7 y"} {:process 10, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 yx 32 3 yx 5 3 yx 6 12 yx 3 5 yx 39 1 yx 44 0 yx 44 2 yx 42 3 yx 46 5 yx 30 6 yx 26 4 yx 30 11 yx 7 1 yx 7 3 yx 26 11 yx 49 9 yx 32 4 yx 17 6 y"} {:process 10, :type :invoke, :f :get, :key "6", :value nil} {:process 23, :type :ok, :f :get, :key "6", :value "x 3 9 yx 22 1 yx 26 5 yx 15 10 yx 16 2 yx 26 9 yx 26 10 yx 30 18 yx 41 3 yx 29 3 yx 8 5 yx 10 8 yx 49 12 y"} {:process 23, :type :invoke, :f :get, :key "2", :value nil} {:process 23, :type :ok, :f :get, :key "2", :value "x 14 1 yx 16 4 yx 30 13 yx 4 2 yx 49 8 yx 10 6 y"} {:process 23, :type :invoke, :f :put, :key "2", :value "x 23 3 y"} {:process 6, :type :ok, :f :put, :key "1", :value "x 6 15 y"} {:process 6, :type :invoke, :f :append, :key "8", :value "x 6 16 y"} {:process 10, :type :ok, :f :get, :key "6", :value "x 3 9 yx 22 1 yx 26 5 yx 15 10 yx 16 2 yx 26 9 yx 26 10 yx 30 18 yx 41 3 yx 29 3 yx 8 5 yx 10 8 yx 49 12 y"} {:process 10, :type :invoke, :f :append, :key "0", :value "x 10 9 y"} {:process 8, :type :ok, :f :append, :key "7", :value "x 8 7 y"} {:process 8, :type :invoke, :f :append, :key "6", :value "x 8 8 y"} {:process 49, :type :ok, :f :put, :key "6", :value "x 49 13 y"} {:process 49, :type :invoke, :f :append, :key "6", :value "x 49 14 y"} {:process 17, :type :ok, :f :append, :key "7", :value "x 17 7 y"} {:process 17, :type :invoke, :f :append, :key "4", :value "x 17 8 y"} {:process 39, :type :ok, :f :append, :key "8", :value "x 39 3 y"} {:process 39, :type :invoke, :f :get, :key "4", :value nil} {:process 23, :type :ok, :f :put, :key "2", :value "x 23 3 y"} {:process 23, :type :invoke, :f :append, :key "5", :value "x 23 4 y"} {:process 2, :type :ok, :f :append, :key "0", :value "x 2 3 y"} {:process 2, :type :invoke, :f :append, :key "0", :value "x 2 4 y"} {:process 6, :type :ok, :f :append, :key "8", :value "x 6 16 y"} {:process 6, :type :invoke, :f :append, :key "6", :value "x 6 17 y"} {:process 39, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 yx 32 3 yx 5 3 yx 6 12 yx 3 5 yx 39 1 yx 44 0 yx 44 2 yx 42 3 yx 46 5 yx 30 6 yx 26 4 yx 30 11 yx 7 1 yx 7 3 yx 26 11 yx 49 9 yx 32 4 yx 17 6 y"} {:process 39, :type :invoke, :f :get, :key "7", :value nil} {:process 10, :type :ok, :f :append, :key "0", :value "x 10 9 y"} {:process 10, :type :invoke, :f :get, :key "8", :value nil} {:process 2, :type :ok, :f :append, :key "0", :value "x 2 4 y"} {:process 2, :type :invoke, :f :get, :key "0", :value nil} {:process 17, :type :ok, :f :append, :key "4", :value "x 17 8 y"} {:process 17, :type :invoke, :f :append, :key "1", :value "x 17 9 y"} {:process 23, :type :ok, :f :append, :key "5", :value "x 23 4 y"} {:process 23, :type :invoke, :f :get, :key "6", :value nil} {:process 2, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 yx 1 3 yx 2 3 yx 11 3 yx 40 1 yx 0 5 yx 46 4 yx 26 2 yx 12 7 yx 11 8 yx 36 1 yx 45 1 yx 16 6 yx 16 7 yx 8 3 yx 4 5 yx 10 9 yx 2 4 y"} {:process 2, :type :invoke, :f :append, :key "2", :value "x 2 5 y"} {:process 8, :type :ok, :f :append, :key "6", :value "x 8 8 y"} {:process 8, :type :invoke, :f :append, :key "3", :value "x 8 9 y"} {:process 40, :type :ok, :f :append, :key "0", :value "x 40 1 y"} {:process 1, :type :ok, :f :append, :key "5", :value "x 1 4 y"} {:process 1, :type :invoke, :f :append, :key "7", :value "x 1 5 y"} {:process 40, :type :invoke, :f :get, :key "2", :value nil} {:process 49, :type :ok, :f :append, :key "6", :value "x 49 14 y"} {:process 49, :type :invoke, :f :put, :key "3", :value "x 49 15 y"} {:process 10, :type :ok, :f :get, :key "8", :value "x 47 5 yx 10 5 yx 18 8 yx 39 3 yx 6 16 y"} {:process 10, :type :invoke, :f :append, :key "2", :value "x 10 10 y"} {:process 23, :type :ok, :f :get, :key "6", :value "x 49 13 yx 8 8 yx 49 14 yx 6 17 y"} {:process 23, :type :invoke, :f :append, :key "1", :value "x 23 5 y"} {:process 17, :type :ok, :f :append, :key "1", :value "x 17 9 y"} {:process 17, :type :invoke, :f :append, :key "8", :value "x 17 10 y"} {:process 8, :type :ok, :f :append, :key "3", :value "x 8 9 y"} {:process 8, :type :invoke, :f :append, :key "7", :value "x 8 10 y"} {:process 49, :type :ok, :f :put, :key "3", :value "x 49 15 y"} {:process 49, :type :invoke, :f :get, :key "0", :value nil} {:process 2, :type :ok, :f :append, :key "2", :value "x 2 5 y"} {:process 2, :type :invoke, :f :get, :key "0", :value nil} {:process 2, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 yx 1 3 yx 2 3 yx 11 3 yx 40 1 yx 0 5 yx 46 4 yx 26 2 yx 12 7 yx 11 8 yx 36 1 yx 45 1 yx 16 6 yx 16 7 yx 8 3 yx 4 5 yx 10 9 yx 2 4 y"} {:process 2, :type :invoke, :f :put, :key "7", :value "x 2 6 y"} {:process 28, :type :ok, :f :append, :key "0", :value "x 28 1 y"} {:process 28, :type :invoke, :f :append, :key "3", :value "x 28 2 y"} {:process 1, :type :ok, :f :append, :key "7", :value "x 1 5 y"} {:process 1, :type :invoke, :f :get, :key "9", :value nil} {:process 49, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 yx 1 3 yx 2 3 yx 11 3 yx 40 1 yx 0 5 yx 46 4 yx 26 2 yx 12 7 yx 11 8 yx 36 1 yx 45 1 yx 16 6 yx 16 7 yx 8 3 yx 4 5 yx 10 9 yx 2 4 yx 28 1 y"} {:process 49, :type :invoke, :f :append, :key "4", :value "x 49 16 y"} {:process 1, :type :ok, :f :get, :key "9", :value "x 6 2 yx 13 0 yx 36 0 yx 3 0 yx 24 0 yx 49 2 yx 18 0 yx 18 1 yx 5 1 yx 21 0 yx 18 4 yx 18 6 yx 41 0 yx 8 2 yx 17 4 yx 20 5 yx 42 1 yx 24 4 yx 11 14 yx 11 15 yx 33 2 yx 29 6 y"} {:process 1, :type :invoke, :f :get, :key "0", :value nil} {:process 1, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 yx 1 3 yx 2 3 yx 11 3 yx 40 1 yx 0 5 yx 46 4 yx 26 2 yx 12 7 yx 11 8 yx 36 1 yx 45 1 yx 16 6 yx 16 7 yx 8 3 yx 4 5 yx 10 9 yx 2 4 yx 28 1 y"} {:process 1, :type :invoke, :f :get, :key "3", :value nil} {:process 10, :type :ok, :f :append, :key "2", :value "x 10 10 y"} {:process 10, :type :invoke, :f :append, :key "1", :value "x 10 11 y"} {:process 23, :type :ok, :f :append, :key "1", :value "x 23 5 y"} {:process 23, :type :invoke, :f :get, :key "5", :value nil} {:process 18, :type :ok, :f :get, :key "9", :value "x 6 2 yx 13 0 yx 36 0 yx 3 0 yx 24 0 yx 49 2 yx 18 0 yx 18 1 yx 5 1 yx 21 0 yx 18 4 yx 18 6 yx 41 0 yx 8 2 yx 17 4 yx 20 5 yx 42 1 yx 24 4 yx 11 14 yx 11 15 yx 33 2 yx 29 6 y"} {:process 18, :type :invoke, :f :append, :key "1", :value "x 18 9 y"} {:process 5, :type :ok, :f :get, :key "6", :value "x 14 0 yx 11 0 yx 31 0 y"} {:process 5, :type :invoke, :f :get, :key "8", :value nil} {:process 5, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 y"} {:process 5, :type :invoke, :f :get, :key "8", :value nil} {:process 5, :type :ok, :f :get, :key "8", :value "x 48 0 yx 49 3 yx 37 1 yx 18 2 yx 0 0 yx 18 5 yx 4 0 yx 21 3 yx 0 4 y"} {:process 5, :type :invoke, :f :get, :key "1", :value nil} {:process 2, :type :ok, :f :put, :key "7", :value "x 2 6 y"} {:process 28, :type :ok, :f :append, :key "3", :value "x 28 2 y"} {:process 2, :type :invoke, :f :append, :key "7", :value "x 2 7 y"} {:process 28, :type :invoke, :f :put, :key "1", :value "x 28 3 y"} {:process 8, :type :ok, :f :append, :key "7", :value "x 8 10 y"} {:process 8, :type :invoke, :f :get, :key "1", :value nil} {:process 17, :type :ok, :f :append, :key "8", :value "x 17 10 y"} {:process 17, :type :invoke, :f :get, :key "5", :value nil} {:process 1, :type :ok, :f :get, :key "3", :value "x 49 15 yx 28 2 y"} {:process 1, :type :invoke, :f :append, :key "3", :value "x 1 6 y"} {:process 10, :type :ok, :f :append, :key "1", :value "x 10 11 y"} {:process 31, :type :ok, :f :put, :key "3", :value "x 31 6 y"} {:process 10, :type :invoke, :f :append, :key "7", :value "x 10 12 y"} {:process 31, :type :invoke, :f :get, :key "7", :value nil} {:process 8, :type :ok, :f :get, :key "1", :value "x 6 15 yx 17 9 yx 23 5 yx 10 11 y"} {:process 8, :type :invoke, :f :append, :key "5", :value "x 8 11 y"} {:process 49, :type :ok, :f :append, :key "4", :value "x 49 16 y"} {:process 49, :type :invoke, :f :put, :key "5", :value "x 49 17 y"} {:process 0, :type :ok, :f :append, :key "8", :value "x 0 8 y"} {:process 0, :type :invoke, :f :append, :key "4", :value "x 0 9 y"} {:process 5, :type :ok, :f :get, :key "1", :value "x 30 0 yx 46 1 yx 30 3 yx 13 1 yx 5 0 yx 15 4 yx 34 0 yx 25 0 yx 18 3 y"} {:process 5, :type :invoke, :f :get, :key "2", :value nil} {:process 5, :type :ok, :f :get, :key "2", :value "x 0 2 yx 11 1 y"} {:process 5, :type :invoke, :f :append, :key "7", :value "x 5 6 y"} {:process 20, :type :ok, :f :append, :key "5", :value "x 20 7 y"} {:process 20, :type :invoke, :f :append, :key "3", :value "x 20 8 y"} {:process 17, :type :ok, :f :get, :key "5", :value "x 43 0 yx 21 4 yx 6 8 yx 41 1 yx 32 1 yx 20 4 yx 46 3 yx 0 7 yx 11 7 yx 13 5 yx 45 0 yx 15 9 yx 11 13 yx 21 7 yx 4 4 yx 49 10 yx 8 4 yx 8 6 yx 23 4 yx 1 4 yx 20 7 y"} {:process 17, :type :invoke, :f :append, :key "4", :value "x 17 11 y"} {:process 31, :type :ok, :f :get, :key "7", :value "x 2 6 yx 8 10 yx 2 7 y"} {:process 31, :type :invoke, :f :put, :key "9", :value "x 31 7 y"} {:process 49, :type :ok, :f :put, :key "5", :value "x 49 17 y"} {:process 49, :type :invoke, :f :get, :key "2", :value nil} {:process 44, :type :ok, :f :put, :key "0", :value "x 44 4 y"} {:process 44, :type :invoke, :f :append, :key "2", :value "x 44 5 y"} {:process 39, :type :ok, :f :get, :key "7", :value "x 2 6 yx 8 10 yx 2 7 y"} {:process 39, :type :invoke, :f :append, :key "8", :value "x 39 4 y"} {:process 49, :type :ok, :f :get, :key "2", :value "x 23 3 yx 2 5 yx 10 10 y"} {:process 49, :type :invoke, :f :get, :key "5", :value nil} {:process 1, :type :ok, :f :append, :key "3", :value "x 1 6 y"} {:process 1, :type :invoke, :f :get, :key "0", :value nil} {:process 8, :type :ok, :f :append, :key "5", :value "x 8 11 y"} {:process 8, :type :invoke, :f :get, :key "1", :value nil} {:process 10, :type :ok, :f :append, :key "7", :value "x 10 12 y"} {:process 10, :type :invoke, :f :append, :key "0", :value "x 10 13 y"} {:process 4, :type :ok, :f :get, :key "7", :value "x 2 6 yx 8 10 yx 2 7 y"} {:process 4, :type :invoke, :f :append, :key "8", :value "x 4 6 y"} {:process 49, :type :ok, :f :get, :key "5", :value "x 49 17 yx 8 11 y"} {:process 49, :type :invoke, :f :append, :key "7", :value "x 49 18 y"} {:process 0, :type :ok, :f :append, :key "4", :value "x 0 9 y"} {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 10 y"} {:process 28, :type :ok, :f :put, :key "1", :value "x 28 3 y"} {:process 28, :type :invoke, :f :get, :key "3", :value nil} {:process 44, :type :ok, :f :append, :key "2", :value "x 44 5 y"} {:process 44, :type :invoke, :f :append, :key "2", :value "x 44 6 y"} {:process 10, :type :ok, :f :append, :key "0", :value "x 10 13 y"} {:process 10, :type :invoke, :f :append, :key "1", :value "x 10 14 y"} {:process 28, :type :ok, :f :get, :key "3", :value "x 31 6 yx 1 6 yx 20 8 y"} {:process 28, :type :invoke, :f :append, :key "9", :value "x 28 4 y"} {:process 8, :type :ok, :f :get, :key "1", :value "x 28 3 y"} {:process 8, :type :invoke, :f :get, :key "1", :value nil} {:process 31, :type :ok, :f :put, :key "9", :value "x 31 7 y"} {:process 31, :type :invoke, :f :append, :key "1", :value "x 31 8 y"} {:process 8, :type :ok, :f :get, :key "1", :value "x 28 3 y"} {:process 8, :type :invoke, :f :append, :key "9", :value "x 8 12 y"} {:process 21, :type :ok, :f :get, :key "0", :value "x 44 4 yx 10 13 y"} {:process 21, :type :invoke, :f :get, :key "8", :value nil} {:process 42, :type :ok, :f :append, :key "4", :value "x 42 4 y"} {:process 42, :type :invoke, :f :put, :key "4", :value "x 42 5 y"} {:process 35, :type :ok, :f :append, :key "5", :value "x 35 3 y"} {:process 35, :type :invoke, :f :append, :key "6", :value "x 35 4 y"} {:process 44, :type :ok, :f :append, :key "2", :value "x 44 6 y"} {:process 44, :type :invoke, :f :get, :key "5", :value nil} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 10 y"} {:process 0, :type :invoke, :f :get, :key "2", :value nil} {:process 0, :type :ok, :f :get, :key "2", :value "x 23 3 yx 2 5 yx 10 10 yx 44 5 yx 46 6 yx 44 6 y"} {:process 0, :type :invoke, :f :get, :key "6", :value nil} {:process 28, :type :ok, :f :append, :key "9", :value "x 28 4 y"} {:process 28, :type :invoke, :f :append, :key "8", :value "x 28 5 y"} {:process 44, :type :ok, :f :get, :key "5", :value "x 49 17 yx 8 11 yx 35 3 y"} {:process 44, :type :invoke, :f :get, :key "3", :value nil} {:process 44, :type :ok, :f :get, :key "3", :value "x 31 6 yx 1 6 yx 20 8 y"} {:process 44, :type :invoke, :f :append, :key "2", :value "x 44 7 y"} {:process 43, :type :ok, :f :append, :key "3", :value "x 43 3 y"} {:process 43, :type :invoke, :f :get, :key "2", :value nil} {:process 43, :type :ok, :f :get, :key "2", :value "x 23 3 yx 2 5 yx 10 10 yx 44 5 yx 46 6 yx 44 6 y"} {:process 43, :type :invoke, :f :append, :key "0", :value "x 43 4 y"} {:process 0, :type :ok, :f :get, :key "6", :value "x 49 13 yx 8 8 yx 49 14 yx 6 17 y"} {:process 0, :type :invoke, :f :append, :key "2", :value "x 0 11 y"} {:process 24, :type :ok, :f :append, :key "2", :value "x 24 7 y"} {:process 24, :type :invoke, :f :get, :key "1", :value nil} {:process 24, :type :ok, :f :get, :key "1", :value "x 28 3 yx 10 14 y"} {:process 24, :type :invoke, :f :append, :key "7", :value "x 24 8 y"} {:process 43, :type :ok, :f :append, :key "0", :value "x 43 4 y"} {:process 43, :type :invoke, :f :get, :key "9", :value nil} {:process 43, :type :ok, :f :get, :key "9", :value "x 31 7 yx 28 4 y"} {:process 43, :type :invoke, :f :append, :key "8", :value "x 43 5 y"} {:process 0, :type :ok, :f :append, :key "2", :value "x 0 11 y"} {:process 28, :type :ok, :f :append, :key "8", :value "x 28 5 y"} {:process 0, :type :invoke, :f :get, :key "0", :value nil} {:process 28, :type :invoke, :f :append, :key "4", :value "x 28 6 y"} {:process 44, :type :ok, :f :append, :key "2", :value "x 44 7 y"} {:process 44, :type :invoke, :f :get, :key "6", :value nil} {:process 1, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 yx 1 3 yx 2 3 yx 11 3 yx 40 1 yx 0 5 yx 46 4 yx 26 2 yx 12 7 yx 11 8 yx 36 1 yx 45 1 yx 16 6 yx 16 7 y"} {:process 1, :type :invoke, :f :get, :key "1", :value nil} {:process 24, :type :ok, :f :append, :key "7", :value "x 24 8 y"} {:process 24, :type :invoke, :f :append, :key "8", :value "x 24 9 y"} {:process 1, :type :ok, :f :get, :key "1", :value "x 3 8 yx 31 3 yx 16 5 yx 48 2 yx 26 8 yx 30 16 y"} {:process 1, :type :invoke, :f :append, :key "0", :value "x 1 7 y"} {:process 44, :type :ok, :f :get, :key "6", :value "x 49 13 yx 8 8 yx 49 14 yx 6 17 yx 22 3 y"} {:process 44, :type :invoke, :f :append, :key "4", :value "x 44 8 y"} {:process 0, :type :ok, :f :get, :key "0", :value "x 44 4 yx 10 13 yx 0 10 yx 43 4 y"} {:process 0, :type :invoke, :f :get, :key "3", :value nil} {:process 0, :type :ok, :f :get, :key "3", :value "x 31 6 yx 1 6 yx 20 8 yx 43 3 y"} {:process 0, :type :invoke, :f :append, :key "5", :value "x 0 12 y"} {:process 28, :type :ok, :f :append, :key "4", :value "x 28 6 y"} {:process 28, :type :invoke, :f :get, :key "3", :value nil} {:process 27, :type :ok, :f :append, :key "7", :value "x 27 4 y"} {:process 27, :type :invoke, :f :append, :key "7", :value "x 27 5 y"} {:process 13, :type :ok, :f :append, :key "1", :value "x 13 6 y"} {:process 43, :type :ok, :f :append, :key "8", :value "x 43 5 y"} {:process 43, :type :invoke, :f :get, :key "0", :value nil} {:process 13, :type :invoke, :f :put, :key "5", :value "x 13 7 y"} {:process 21, :type :ok, :f :get, :key "8", :value "x 47 5 yx 10 5 yx 18 8 yx 39 3 yx 6 16 yx 17 10 yx 0 8 yx 28 5 y"} {:process 21, :type :invoke, :f :get, :key "7", :value nil} {:process 40, :type :ok, :f :get, :key "2", :value "x 23 3 yx 2 5 yx 10 10 yx 44 5 yx 46 6 yx 44 6 yx 24 7 yx 44 7 yx 0 11 y"} {:process 40, :type :invoke, :f :get, :key "4", :value nil} {:process 36, :type :ok, :f :append, :key "0", :value "x 36 2 y"} {:process 36, :type :invoke, :f :get, :key "2", :value nil} {:process 0, :type :ok, :f :append, :key "5", :value "x 0 12 y"} {:process 0, :type :invoke, :f :get, :key "2", :value nil} {:process 24, :type :ok, :f :append, :key "8", :value "x 24 9 y"} {:process 24, :type :invoke, :f :append, :key "1", :value "x 24 10 y"} {:process 44, :type :ok, :f :append, :key "4", :value "x 44 8 y"} {:process 44, :type :invoke, :f :get, :key "0", :value nil} {:process 40, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 yx 32 3 yx 5 3 yx 6 12 yx 3 5 yx 39 1 yx 44 0 yx 44 2 yx 42 3 yx 46 5 yx 30 6 yx 26 4 yx 30 11 yx 7 1 yx 7 3 yx 26 11 yx 49 9 yx 32 4 yx 17 6 yx 17 8 yx 49 16 yx 0 9 yx 17 11 yx 42 4 yx 28 6 y"} {:process 40, :type :invoke, :f :append, :key "9", :value "x 40 2 y"} {:process 0, :type :ok, :f :get, :key "2", :value "x 23 3 yx 2 5 yx 10 10 yx 44 5 yx 46 6 yx 44 6 yx 24 7 yx 44 7 yx 0 11 y"} {:process 0, :type :invoke, :f :append, :key "9", :value "x 0 13 y"} {:process 36, :type :ok, :f :get, :key "2", :value "x 23 3 yx 2 5 yx 10 10 yx 44 5 yx 46 6 yx 44 6 yx 24 7 yx 44 7 yx 0 11 y"} {:process 36, :type :invoke, :f :get, :key "3", :value nil} {:process 23, :type :ok, :f :get, :key "5", :value "x 43 0 yx 21 4 yx 6 8 yx 41 1 yx 32 1 yx 20 4 yx 46 3 yx 0 7 yx 11 7 yx 13 5 yx 45 0 yx 15 9 yx 11 13 y"} {:process 23, :type :invoke, :f :append, :key "1", :value "x 23 6 y"} {:process 44, :type :ok, :f :get, :key "0", :value "x 44 4 yx 10 13 yx 0 10 yx 43 4 yx 36 2 y"} {:process 44, :type :invoke, :f :append, :key "5", :value "x 44 9 y"} {:process 36, :type :ok, :f :get, :key "3", :value "x 31 6 yx 1 6 yx 20 8 yx 43 3 y"} {:process 36, :type :invoke, :f :get, :key "3", :value nil} {:process 13, :type :ok, :f :put, :key "5", :value "x 13 7 y"} {:process 13, :type :invoke, :f :get, :key "2", :value nil} {:process 27, :type :ok, :f :append, :key "7", :value "x 27 5 y"} {:process 27, :type :invoke, :f :append, :key "2", :value "x 27 6 y"} {:process 24, :type :ok, :f :append, :key "1", :value "x 24 10 y"} {:process 24, :type :invoke, :f :append, :key "0", :value "x 24 11 y"} {:process 0, :type :ok, :f :append, :key "9", :value "x 0 13 y"} {:process 0, :type :invoke, :f :get, :key "9", :value nil} {:process 13, :type :ok, :f :get, :key "2", :value "x 23 3 yx 2 5 yx 10 10 yx 44 5 yx 46 6 yx 44 6 yx 24 7 yx 44 7 yx 0 11 y"} {:process 13, :type :invoke, :f :append, :key "8", :value "x 13 8 y"} {:process 0, :type :ok, :f :get, :key "9", :value "x 31 7 yx 28 4 yx 0 13 y"} {:process 0, :type :invoke, :f :append, :key "4", :value "x 0 14 y"} {:process 27, :type :ok, :f :append, :key "2", :value "x 27 6 y"} {:process 27, :type :invoke, :f :put, :key "6", :value "x 27 7 y"} {:process 45, :type :ok, :f :put, :key "2", :value "x 45 2 y"} {:process 45, :type :invoke, :f :append, :key "4", :value "x 45 3 y"} {:process 44, :type :ok, :f :append, :key "5", :value "x 44 9 y"} {:process 44, :type :invoke, :f :get, :key "6", :value nil} {:process 13, :type :ok, :f :append, :key "8", :value "x 13 8 y"} {:process 13, :type :invoke, :f :get, :key "5", :value nil} {:process 13, :type :ok, :f :get, :key "5", :value "x 13 7 yx 44 9 y"} {:process 13, :type :invoke, :f :get, :key "5", :value nil} {:process 28, :type :ok, :f :get, :key "3", :value "x 37 5 y"} {:process 28, :type :invoke, :f :append, :key "7", :value "x 28 7 y"} {:process 43, :type :ok, :f :get, :key "0", :value "x 15 8 y"} {:process 43, :type :invoke, :f :get, :key "0", :value nil} {:process 13, :type :ok, :f :get, :key "5", :value "x 13 7 yx 44 9 y"} {:process 13, :type :invoke, :f :append, :key "2", :value "x 13 9 y"} {:process 0, :type :ok, :f :append, :key "4", :value "x 0 14 y"} {:process 0, :type :invoke, :f :get, :key "5", :value nil} {:process 27, :type :ok, :f :put, :key "6", :value "x 27 7 y"} {:process 27, :type :invoke, :f :append, :key "1", :value "x 27 8 y"} {:process 45, :type :ok, :f :append, :key "4", :value "x 45 3 y"} {:process 45, :type :invoke, :f :get, :key "3", :value nil} {:process 43, :type :ok, :f :get, :key "0", :value "x 15 8 y"} {:process 43, :type :invoke, :f :get, :key "3", :value nil} {:process 27, :type :ok, :f :append, :key "1", :value "x 27 8 y"} {:process 27, :type :invoke, :f :append, :key "1", :value "x 27 9 y"} {:process 13, :type :ok, :f :append, :key "2", :value "x 13 9 y"} {:process 13, :type :invoke, :f :append, :key "4", :value "x 13 10 y"} {:process 0, :type :ok, :f :get, :key "5", :value "x 13 7 yx 44 9 yx 14 2 y"} {:process 0, :type :invoke, :f :get, :key "9", :value nil} {:process 11, :type :ok, :f :append, :key "3", :value "x 11 16 y"} {:process 11, :type :invoke, :f :get, :key "0", :value nil} {:process 0, :type :ok, :f :get, :key "9", :value "x 31 7 yx 28 4 yx 0 13 y"} {:process 0, :type :invoke, :f :get, :key "5", :value nil} {:process 11, :type :ok, :f :get, :key "0", :value "x 44 4 yx 10 13 yx 0 10 yx 43 4 yx 36 2 y"} {:process 11, :type :invoke, :f :get, :key "7", :value nil} {:process 11, :type :ok, :f :get, :key "7", :value "x 2 6 yx 8 10 yx 2 7 yx 10 12 yx 49 18 yx 24 8 yx 27 4 yx 27 5 y"} {:process 11, :type :invoke, :f :append, :key "3", :value "x 11 17 y"} {:process 25, :type :ok, :f :put, :key "0", :value "x 25 1 y"} {:process 25, :type :invoke, :f :append, :key "9", :value "x 25 2 y"} {:process 27, :type :ok, :f :append, :key "1", :value "x 27 9 y"} {:process 27, :type :invoke, :f :append, :key "9", :value "x 27 10 y"} {:process 13, :type :ok, :f :append, :key "4", :value "x 13 10 y"} {:process 13, :type :invoke, :f :get, :key "0", :value nil} {:process 36, :type :ok, :f :get, :key "3", :value "x 37 5 y"} {:process 36, :type :invoke, :f :append, :key "0", :value "x 36 3 y"} {:process 37, :type :ok, :f :put, :key "3", :value "x 37 5 y"} {:process 37, :type :invoke, :f :get, :key "7", :value nil} {:process 37, :type :ok, :f :get, :key "7", :value "x 2 6 yx 8 10 yx 2 7 yx 10 12 yx 49 18 yx 24 8 yx 27 4 yx 27 5 y"} {:process 37, :type :invoke, :f :append, :key "2", :value "x 37 6 y"} {:process 16, :type :ok, :f :append, :key "5", :value "x 16 8 y"} {:process 16, :type :invoke, :f :append, :key "1", :value "x 16 9 y"} {:process 44, :type :ok, :f :get, :key "6", :value "x 27 7 y"} {:process 44, :type :invoke, :f :append, :key "5", :value "x 44 10 y"} {:process 16, :type :ok, :f :append, :key "1", :value "x 16 9 y"} {:process 16, :type :invoke, :f :get, :key "8", :value nil} {:process 25, :type :ok, :f :append, :key "9", :value "x 25 2 y"} {:process 25, :type :invoke, :f :append, :key "4", :value "x 25 3 y"} {:process 21, :type :ok, :f :get, :key "7", :value "x 2 6 yx 8 10 yx 2 7 yx 10 12 yx 49 18 yx 24 8 yx 27 4 yx 27 5 y"} {:process 21, :type :invoke, :f :get, :key "2", :value nil} {:process 45, :type :ok, :f :get, :key "3", :value "x 15 6 yx 49 5 yx 49 6 yx 0 1 yx 4 1 yx 20 0 yx 31 1 y"} {:process 45, :type :invoke, :f :get, :key "1", :value nil} {:process 16, :type :ok, :f :get, :key "8", :value "x 47 5 yx 10 5 yx 18 8 yx 39 3 yx 6 16 yx 17 10 yx 0 8 yx 28 5 yx 43 5 yx 24 9 yx 13 8 y"} {:process 16, :type :invoke, :f :append, :key "6", :value "x 16 10 y"} {:process 45, :type :ok, :f :get, :key "1", :value "x 30 0 yx 46 1 yx 30 3 yx 13 1 yx 5 0 yx 15 4 yx 34 0 yx 25 0 yx 18 3 y"} {:process 45, :type :invoke, :f :append, :key "9", :value "x 45 4 y"} {:process 7, :type :ok, :f :append, :key "5", :value "x 7 4 y"} {:process 7, :type :invoke, :f :get, :key "4", :value nil} {:process 7, :type :ok, :f :get, :key "4", :value "x 6 0 yx 26 1 yx 46 2 yx 3 1 yx 12 6 yx 16 1 yx 15 3 yx 8 0 yx 38 0 yx 27 2 yx 19 2 yx 19 3 yx 29 1 yx 49 7 yx 32 3 yx 5 3 yx 6 12 yx 3 5 yx 39 1 yx 44 0 yx 44 2 yx 42 3 yx 46 5 yx 30 6 yx 26 4 yx 30 11 yx 7 1 yx 7 3 yx 26 11 yx 49 9 yx 32 4 yx 17 6 yx 17 8 yx 49 16 yx 0 9 yx 17 11 yx 42 4 yx 28 6 yx 44 8 yx 0 14 yx 45 3 yx 13 10 y"} {:process 7, :type :invoke, :f :get, :key "9", :value nil} {:process 43, :type :ok, :f :get, :key "3", :value "x 37 5 y"} {:process 43, :type :invoke, :f :append, :key "1", :value "x 43 6 y"} {:process 21, :type :ok, :f :get, :key "2", :value "x 45 2 yx 27 6 yx 13 9 y"} {:process 21, :type :invoke, :f :get, :key "3", :value nil} {:process 0, :type :ok, :f :get, :key "5", :value "x 13 7 yx 44 9 yx 14 2 yx 16 8 yx 7 4 y"} {:process 0, :type :invoke, :f :append, :key "5", :value "x 0 15 y"} {:process 16, :type :ok, :f :append, :key "6", :value "x 16 10 y"} {:process 16, :type :invoke, :f :append, :key "9", :value "x 16 11 y"} {:process 7, :type :ok, :f :get, :key "9", :value "x 31 7 yx 28 4 yx 0 13 yx 27 10 yx 25 2 y"} {:process 7, :type :invoke, :f :get, :key "0", :value nil} {:process 21, :type :ok, :f :get, :key "3", :value "x 15 6 yx 49 5 yx 49 6 yx 0 1 yx 4 1 yx 20 0 yx 31 1 y"} {:process 21, :type :invoke, :f :append, :key "2", :value "x 21 8 y"} {:process 7, :type :ok, :f :get, :key "0", :value "x 25 1 y"} {:process 7, :type :invoke, :f :get, :key "6", :value nil} {:process 13, :type :ok, :f :get, :key "0", :value "x 25 1 y"} {:process 13, :type :invoke, :f :append, :key "1", :value "x 13 11 y"} {:process 7, :type :ok, :f :get, :key "6", :value "x 14 0 yx 11 0 yx 31 0 y"} {:process 7, :type :invoke, :f :append, :key "9", :value "x 7 5 y"} {:process 39, :type :ok, :f :append, :key "8", :value "x 39 4 y"} {:process 39, :type :invoke, :f :append, :key "9", :value "x 39 5 y"} {:process 39, :type :ok, :f :append, :key "9", :value "x 39 5 y"} {:process 39, :type :invoke, :f :append, :key "5", :value "x 39 6 y"} {:process 20, :type :ok, :f :append, :key "3", :value "x 20 8 y"} {:process 20, :type :invoke, :f :append, :key "9", :value "x 20 9 y"} {:process 23, :type :ok, :f :append, :key "1", :value "x 23 6 y"} {:process 23, :type :invoke, :f :append, :key "7", :value "x 23 7 y"} {:process 2, :type :ok, :f :append, :key "7", :value "x 2 7 y"} {:process 2, :type :invoke, :f :get, :key "2", :value nil} {:process 39, :type :ok, :f :append, :key "5", :value "x 39 6 y"} {:process 39, :type :invoke, :f :append, :key "4", :value "x 39 7 y"} {:process 2, :type :ok, :f :get, :key "2", :value "x 45 2 yx 27 6 yx 13 9 yx 48 5 y"} {:process 2, :type :invoke, :f :get, :key "2", :value nil} {:process 10, :type :ok, :f :append, :key "1", :value "x 10 14 y"} {:process 10, :type :invoke, :f :put, :key "9", :value "x 10 15 y"} {:process 23, :type :ok, :f :append, :key "7", :value "x 23 7 y"} {:process 23, :type :invoke, :f :append, :key "9", :value "x 23 8 y"} {:process 12, :type :ok, :f :append, :key "2", :value "x 12 9 y"} {:process 12, :type :invoke, :f :append, :key "2", :value "x 12 10 y"} {:process 2, :type :ok, :f :get, :key "2", :value "x 45 2 yx 27 6 yx 13 9 yx 48 5 yx 12 9 y"} {:process 2, :type :invoke, :f :put, :key "4", :value "x 2 8 y"} {:process 23, :type :ok, :f :append, :key "9", :value "x 23 8 y"} {:process 23, :type :invoke, :f :append, :key "2", :value "x 23 9 y"} {:process 39, :type :ok, :f :append, :key "4", :value "x 39 7 y"} {:process 39, :type :invoke, :f :get, :key "7", :value nil} {:process 3, :type :ok, :f :put, :key "6", :value "x 3 9 y"} {:process 3, :type :invoke, :f :append, :key "3", :value "x 3 10 y"} {:process 12, :type :ok, :f :append, :key "2", :value "x 12 10 y"} {:process 12, :type :invoke, :f :get, :key "4", :value nil} {:process 10, :type :ok, :f :put, :key "9", :value "x 10 15 y"} {:process 10, :type :invoke, :f :append, :key "0", :value "x 10 16 y"} {:process 35, :type :ok, :f :append, :key "6", :value "x 35 4 y"} {:process 35, :type :invoke, :f :get, :key "0", :value nil} {:process 2, :type :ok, :f :put, :key "4", :value "x 2 8 y"} {:process 2, :type :invoke, :f :append, :key "0", :value "x 2 9 y"} {:process 35, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 y"} {:process 35, :type :invoke, :f :get, :key "7", :value nil} {:process 39, :type :ok, :f :get, :key "7", :value "x 2 6 yx 8 10 yx 2 7 yx 10 12 yx 49 18 yx 24 8 yx 27 4 yx 27 5 yx 23 7 y"} {:process 39, :type :invoke, :f :get, :key "8", :value nil} {:process 12, :type :ok, :f :get, :key "4", :value "x 2 8 y"} {:process 12, :type :invoke, :f :get, :key "4", :value nil} {:process 31, :type :ok, :f :append, :key "1", :value "x 31 8 y"} {:process 31, :type :invoke, :f :append, :key "6", :value "x 31 9 y"} {:process 17, :type :ok, :f :append, :key "4", :value "x 17 11 y"} {:process 17, :type :invoke, :f :get, :key "7", :value nil} {:process 12, :type :ok, :f :get, :key "4", :value "x 2 8 y"} {:process 12, :type :invoke, :f :get, :key "2", :value nil} {:process 23, :type :ok, :f :append, :key "2", :value "x 23 9 y"} {:process 23, :type :invoke, :f :append, :key "9", :value "x 23 10 y"} {:process 12, :type :ok, :f :get, :key "2", :value "x 45 2 yx 27 6 yx 13 9 yx 48 5 yx 12 9 yx 12 10 yx 23 9 y"} {:process 12, :type :invoke, :f :get, :key "2", :value nil} {:process 35, :type :ok, :f :get, :key "7", :value "x 2 6 yx 8 10 yx 2 7 yx 10 12 yx 49 18 yx 24 8 yx 27 4 yx 27 5 yx 23 7 y"} {:process 35, :type :invoke, :f :append, :key "6", :value "x 35 5 y"} {:process 49, :type :ok, :f :append, :key "7", :value "x 49 18 y"} {:process 49, :type :invoke, :f :append, :key "9", :value "x 49 19 y"} {:process 39, :type :ok, :f :get, :key "8", :value "x 47 5 yx 10 5 yx 18 8 yx 39 3 yx 6 16 yx 17 10 yx 0 8 yx 28 5 yx 43 5 yx 24 9 yx 13 8 yx 39 4 y"} {:process 39, :type :invoke, :f :append, :key "5", :value "x 39 8 y"} {:process 3, :type :ok, :f :append, :key "3", :value "x 3 10 y"} {:process 3, :type :invoke, :f :append, :key "6", :value "x 3 11 y"} {:process 42, :type :ok, :f :put, :key "4", :value "x 42 5 y"} {:process 42, :type :invoke, :f :get, :key "7", :value nil} {:process 12, :type :ok, :f :get, :key "2", :value "x 45 2 yx 27 6 yx 13 9 yx 48 5 yx 12 9 yx 12 10 yx 23 9 y"} {:process 12, :type :invoke, :f :put, :key "7", :value "x 12 11 y"} {:process 42, :type :ok, :f :get, :key "7", :value "x 2 6 yx 8 10 yx 2 7 yx 10 12 yx 49 18 yx 24 8 yx 27 4 yx 27 5 yx 23 7 y"} {:process 42, :type :invoke, :f :get, :key "7", :value nil} {:process 10, :type :ok, :f :append, :key "0", :value "x 10 16 y"} {:process 8, :type :ok, :f :append, :key "9", :value "x 8 12 y"} {:process 10, :type :invoke, :f :append, :key "3", :value "x 10 17 y"} {:process 8, :type :invoke, :f :get, :key "6", :value nil} {:process 49, :type :ok, :f :append, :key "9", :value "x 49 19 y"} {:process 49, :type :invoke, :f :append, :key "9", :value "x 49 20 y"} {:process 42, :type :ok, :f :get, :key "7", :value "x 2 6 yx 8 10 yx 2 7 yx 10 12 yx 49 18 yx 24 8 yx 27 4 yx 27 5 yx 23 7 y"} {:process 42, :type :invoke, :f :get, :key "1", :value nil} {:process 42, :type :ok, :f :get, :key "1", :value "x 28 3 yx 10 14 yx 13 6 yx 24 10 yx 27 8 yx 27 9 yx 16 9 yx 23 6 yx 31 8 y"} {:process 42, :type :invoke, :f :append, :key "6", :value "x 42 6 y"} {:process 12, :type :ok, :f :put, :key "7", :value "x 12 11 y"} {:process 12, :type :invoke, :f :get, :key "4", :value nil} {:process 39, :type :ok, :f :append, :key "5", :value "x 39 8 y"} {:process 39, :type :invoke, :f :append, :key "3", :value "x 39 9 y"} {:process 3, :type :ok, :f :append, :key "6", :value "x 3 11 y"} {:process 3, :type :invoke, :f :get, :key "5", :value nil} {:process 8, :type :ok, :f :get, :key "6", :value "x 9 1 yx 35 4 yx 3 11 y"} {:process 8, :type :invoke, :f :append, :key "3", :value "x 8 13 y"} {:process 10, :type :ok, :f :append, :key "3", :value "x 10 17 y"} {:process 10, :type :invoke, :f :get, :key "2", :value nil} {:process 12, :type :ok, :f :get, :key "4", :value "x 42 5 y"} {:process 12, :type :invoke, :f :get, :key "8", :value nil} {:process 12, :type :ok, :f :get, :key "8", :value "x 47 5 yx 10 5 yx 18 8 yx 39 3 yx 6 16 yx 17 10 yx 0 8 yx 28 5 yx 43 5 yx 24 9 yx 13 8 yx 39 4 y"} {:process 12, :type :invoke, :f :get, :key "8", :value nil} {:process 39, :type :ok, :f :append, :key "3", :value "x 39 9 y"} {:process 39, :type :invoke, :f :get, :key "6", :value nil} {:process 42, :type :ok, :f :append, :key "6", :value "x 42 6 y"} {:process 42, :type :invoke, :f :get, :key "2", :value nil} {:process 12, :type :ok, :f :get, :key "8", :value "x 47 5 yx 10 5 yx 18 8 yx 39 3 yx 6 16 yx 17 10 yx 0 8 yx 28 5 yx 43 5 yx 24 9 yx 13 8 yx 39 4 y"} {:process 12, :type :invoke, :f :get, :key "5", :value nil} {:process 3, :type :ok, :f :get, :key "5", :value "x 13 7 yx 44 9 yx 14 2 yx 16 8 yx 7 4 yx 39 6 yx 39 8 y"} {:process 3, :type :invoke, :f :get, :key "8", :value nil} {:process 8, :type :ok, :f :append, :key "3", :value "x 8 13 y"} {:process 8, :type :invoke, :f :append, :key "3", :value "x 8 14 y"} {:process 49, :type :ok, :f :append, :key "9", :value "x 49 20 y"} {:process 49, :type :invoke, :f :get, :key "9", :value nil} {:process 10, :type :ok, :f :get, :key "2", :value "x 45 2 yx 27 6 yx 13 9 yx 48 5 yx 12 9 yx 12 10 yx 23 9 y"} {:process 10, :type :invoke, :f :get, :key "0", :value nil} {:process 49, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 y"} {:process 49, :type :invoke, :f :get, :key "5", :value nil} {:process 39, :type :ok, :f :get, :key "6", :value "x 9 1 yx 35 4 yx 3 11 yx 42 6 y"} {:process 39, :type :invoke, :f :put, :key "5", :value "x 39 10 y"} {:process 12, :type :ok, :f :get, :key "5", :value "x 13 7 yx 44 9 yx 14 2 yx 16 8 yx 7 4 yx 39 6 yx 39 8 y"} {:process 12, :type :invoke, :f :get, :key "2", :value nil} {:process 49, :type :ok, :f :get, :key "5", :value "x 13 7 yx 44 9 yx 14 2 yx 16 8 yx 7 4 yx 39 6 yx 39 8 y"} {:process 49, :type :invoke, :f :get, :key "8", :value nil} {:process 28, :type :ok, :f :append, :key "7", :value "x 28 7 y"} {:process 28, :type :invoke, :f :get, :key "3", :value nil} {:process 28, :type :ok, :f :get, :key "3", :value "x 31 6 yx 1 6 yx 20 8 yx 43 3 yx 11 17 yx 3 10 yx 10 17 yx 39 9 yx 8 13 y"} {:process 28, :type :invoke, :f :append, :key "9", :value "x 28 8 y"} {:process 42, :type :ok, :f :get, :key "2", :value "x 45 2 yx 27 6 yx 13 9 yx 48 5 yx 12 9 yx 12 10 yx 23 9 y"} {:process 42, :type :invoke, :f :get, :key "4", :value nil} {:process 42, :type :ok, :f :get, :key "4", :value "x 42 5 y"} {:process 42, :type :invoke, :f :append, :key "0", :value "x 42 7 y"} {:process 10, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 y"} {:process 10, :type :invoke, :f :get, :key "3", :value nil} {:process 3, :type :ok, :f :get, :key "8", :value "x 47 5 yx 10 5 yx 18 8 yx 39 3 yx 6 16 yx 17 10 yx 0 8 yx 28 5 yx 43 5 yx 24 9 yx 13 8 yx 39 4 y"} {:process 3, :type :invoke, :f :append, :key "9", :value "x 3 12 y"} {:process 22, :type :ok, :f :append, :key "6", :value "x 22 3 y"} {:process 22, :type :invoke, :f :append, :key "7", :value "x 22 4 y"} {:process 49, :type :ok, :f :get, :key "8", :value "x 47 5 yx 10 5 yx 18 8 yx 39 3 yx 6 16 yx 17 10 yx 0 8 yx 28 5 yx 43 5 yx 24 9 yx 13 8 yx 39 4 y"} {:process 49, :type :invoke, :f :append, :key "4", :value "x 49 21 y"} {:process 10, :type :ok, :f :get, :key "3", :value "x 31 6 yx 1 6 yx 20 8 yx 43 3 yx 11 17 yx 3 10 yx 10 17 yx 39 9 yx 8 13 y"} {:process 10, :type :invoke, :f :append, :key "2", :value "x 10 18 y"} {:process 17, :type :ok, :f :get, :key "7", :value "x 12 11 yx 28 7 y"} {:process 17, :type :invoke, :f :get, :key "6", :value nil} {:process 39, :type :ok, :f :put, :key "5", :value "x 39 10 y"} {:process 39, :type :invoke, :f :get, :key "8", :value nil} {:process 8, :type :ok, :f :append, :key "3", :value "x 8 14 y"} {:process 8, :type :invoke, :f :append, :key "1", :value "x 8 15 y"} {:process 3, :type :ok, :f :append, :key "9", :value "x 3 12 y"} {:process 10, :type :ok, :f :append, :key "2", :value "x 10 18 y"} {:process 3, :type :invoke, :f :append, :key "1", :value "x 3 13 y"} {:process 10, :type :invoke, :f :append, :key "0", :value "x 10 19 y"} {:process 28, :type :ok, :f :append, :key "9", :value "x 28 8 y"} {:process 28, :type :invoke, :f :append, :key "8", :value "x 28 9 y"} {:process 39, :type :ok, :f :get, :key "8", :value "x 47 5 yx 10 5 yx 18 8 yx 39 3 yx 6 16 yx 17 10 yx 0 8 yx 28 5 yx 43 5 yx 24 9 yx 13 8 yx 39 4 y"} {:process 39, :type :invoke, :f :get, :key "6", :value nil} {:process 17, :type :ok, :f :get, :key "6", :value "x 9 1 yx 35 4 yx 3 11 yx 42 6 y"} {:process 17, :type :invoke, :f :get, :key "9", :value nil} {:process 39, :type :ok, :f :get, :key "6", :value "x 9 1 yx 35 4 yx 3 11 yx 42 6 y"} {:process 39, :type :invoke, :f :get, :key "7", :value nil} {:process 42, :type :ok, :f :append, :key "0", :value "x 42 7 y"} {:process 42, :type :invoke, :f :append, :key "0", :value "x 42 8 y"} {:process 22, :type :ok, :f :append, :key "7", :value "x 22 4 y"} {:process 22, :type :invoke, :f :get, :key "3", :value nil} {:process 36, :type :ok, :f :append, :key "0", :value "x 36 3 y"} {:process 36, :type :invoke, :f :get, :key "2", :value nil} {:process 17, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 y"} {:process 17, :type :invoke, :f :append, :key "3", :value "x 17 12 y"} {:process 39, :type :ok, :f :get, :key "7", :value "x 12 11 yx 28 7 yx 22 4 y"} {:process 39, :type :invoke, :f :append, :key "7", :value "x 39 11 y"} {:process 3, :type :ok, :f :append, :key "1", :value "x 3 13 y"} {:process 3, :type :invoke, :f :append, :key "0", :value "x 3 14 y"} {:process 28, :type :ok, :f :append, :key "8", :value "x 28 9 y"} {:process 28, :type :invoke, :f :append, :key "9", :value "x 28 10 y"} {:process 10, :type :ok, :f :append, :key "0", :value "x 10 19 y"} {:process 10, :type :invoke, :f :append, :key "2", :value "x 10 20 y"} {:process 36, :type :ok, :f :get, :key "2", :value "x 45 2 yx 27 6 yx 13 9 yx 48 5 yx 12 9 yx 12 10 yx 23 9 yx 10 18 y"} {:process 36, :type :invoke, :f :append, :key "0", :value "x 36 4 y"} {:process 22, :type :ok, :f :get, :key "3", :value "x 31 6 yx 1 6 yx 20 8 yx 43 3 yx 11 17 yx 3 10 yx 10 17 yx 39 9 yx 8 13 yx 8 14 y"} {:process 22, :type :invoke, :f :append, :key "3", :value "x 22 5 y"} {:process 42, :type :ok, :f :append, :key "0", :value "x 42 8 y"} {:process 42, :type :invoke, :f :append, :key "4", :value "x 42 9 y"} {:process 36, :type :ok, :f :append, :key "0", :value "x 36 4 y"} {:process 36, :type :invoke, :f :get, :key "5", :value nil} {:process 39, :type :ok, :f :append, :key "7", :value "x 39 11 y"} {:process 39, :type :invoke, :f :append, :key "4", :value "x 39 12 y"} {:process 28, :type :ok, :f :append, :key "9", :value "x 28 10 y"} {:process 28, :type :invoke, :f :append, :key "3", :value "x 28 11 y"} {:process 22, :type :ok, :f :append, :key "3", :value "x 22 5 y"} {:process 22, :type :invoke, :f :get, :key "2", :value nil} {:process 10, :type :ok, :f :append, :key "2", :value "x 10 20 y"} {:process 10, :type :invoke, :f :get, :key "6", :value nil} {:process 22, :type :ok, :f :get, :key "2", :value "x 45 2 yx 27 6 yx 13 9 yx 48 5 yx 12 9 yx 12 10 yx 23 9 yx 10 18 yx 10 20 y"} {:process 22, :type :invoke, :f :append, :key "3", :value "x 22 6 y"} {:process 24, :type :ok, :f :append, :key "0", :value "x 24 11 y"} {:process 24, :type :invoke, :f :get, :key "0", :value nil} {:process 42, :type :ok, :f :append, :key "4", :value "x 42 9 y"} {:process 3, :type :ok, :f :append, :key "0", :value "x 3 14 y"} {:process 42, :type :invoke, :f :append, :key "7", :value "x 42 10 y"} {:process 3, :type :invoke, :f :get, :key "2", :value nil} {:process 36, :type :ok, :f :get, :key "5", :value "x 39 10 y"} {:process 36, :type :invoke, :f :append, :key "9", :value "x 36 5 y"} {:process 28, :type :ok, :f :append, :key "3", :value "x 28 11 y"} {:process 28, :type :invoke, :f :put, :key "1", :value "x 28 12 y"} {:process 22, :type :ok, :f :append, :key "3", :value "x 22 6 y"} {:process 22, :type :invoke, :f :get, :key "8", :value nil} {:process 39, :type :ok, :f :append, :key "4", :value "x 39 12 y"} {:process 39, :type :invoke, :f :get, :key "4", :value nil} {:process 12, :type :ok, :f :get, :key "2", :value "x 14 1 yx 16 4 yx 30 13 y"} {:process 12, :type :invoke, :f :append, :key "0", :value "x 12 12 y"} {:process 39, :type :ok, :f :get, :key "4", :value "x 42 5 yx 49 21 yx 42 9 yx 39 12 y"} {:process 39, :type :invoke, :f :get, :key "9", :value nil} {:process 3, :type :ok, :f :get, :key "2", :value "x 45 2 yx 27 6 yx 13 9 yx 48 5 yx 12 9 yx 12 10 yx 23 9 yx 10 18 yx 10 20 y"} {:process 3, :type :invoke, :f :get, :key "3", :value nil} {:process 22, :type :ok, :f :get, :key "8", :value "x 47 5 yx 10 5 yx 18 8 yx 39 3 yx 6 16 yx 17 10 yx 0 8 yx 28 5 yx 43 5 yx 24 9 yx 13 8 yx 39 4 yx 28 9 y"} {:process 22, :type :invoke, :f :append, :key "8", :value "x 22 7 y"} {:process 15, :type :ok, :f :append, :key "0", :value "x 15 12 y"} {:process 15, :type :invoke, :f :append, :key "3", :value "x 15 13 y"} {:process 3, :type :ok, :f :get, :key "3", :value "x 31 6 yx 1 6 yx 20 8 yx 43 3 yx 11 17 yx 3 10 yx 10 17 yx 39 9 yx 8 13 yx 8 14 yx 22 5 yx 28 11 yx 22 6 y"} {:process 3, :type :invoke, :f :get, :key "3", :value nil} {:process 36, :type :ok, :f :append, :key "9", :value "x 36 5 y"} {:process 36, :type :invoke, :f :append, :key "9", :value "x 36 6 y"} {:process 42, :type :ok, :f :append, :key "7", :value "x 42 10 y"} {:process 42, :type :invoke, :f :append, :key "6", :value "x 42 11 y"} {:process 24, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 yx 42 7 yx 36 3 yx 10 19 yx 42 8 yx 36 4 yx 24 11 yx 3 14 yx 15 12 y"} {:process 24, :type :invoke, :f :get, :key "5", :value nil} {:process 3, :type :ok, :f :get, :key "3", :value "x 31 6 yx 1 6 yx 20 8 yx 43 3 yx 11 17 yx 3 10 yx 10 17 yx 39 9 yx 8 13 yx 8 14 yx 22 5 yx 28 11 yx 22 6 y"} {:process 3, :type :invoke, :f :get, :key "9", :value nil} {:process 39, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 y"} {:process 39, :type :invoke, :f :put, :key "3", :value "x 39 13 y"} {:process 3, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 y"} {:process 3, :type :invoke, :f :append, :key "6", :value "x 3 15 y"} {:process 28, :type :ok, :f :put, :key "1", :value "x 28 12 y"} {:process 28, :type :invoke, :f :append, :key "8", :value "x 28 13 y"} {:process 22, :type :ok, :f :append, :key "8", :value "x 22 7 y"} {:process 22, :type :invoke, :f :append, :key "3", :value "x 22 8 y"} {:process 15, :type :ok, :f :append, :key "3", :value "x 15 13 y"} {:process 15, :type :invoke, :f :get, :key "4", :value nil} {:process 24, :type :ok, :f :get, :key "5", :value "x 39 10 y"} {:process 24, :type :invoke, :f :get, :key "8", :value nil} {:process 36, :type :ok, :f :append, :key "9", :value "x 36 6 y"} {:process 36, :type :invoke, :f :get, :key "4", :value nil} {:process 36, :type :ok, :f :get, :key "4", :value "x 42 5 yx 49 21 yx 42 9 yx 39 12 y"} {:process 36, :type :invoke, :f :append, :key "0", :value "x 36 7 y"} {:process 28, :type :ok, :f :append, :key "8", :value "x 28 13 y"} {:process 28, :type :invoke, :f :put, :key "8", :value "x 28 14 y"} {:process 22, :type :ok, :f :append, :key "3", :value "x 22 8 y"} {:process 22, :type :invoke, :f :get, :key "9", :value nil} {:process 3, :type :ok, :f :append, :key "6", :value "x 3 15 y"} {:process 3, :type :invoke, :f :get, :key "1", :value nil} {:process 44, :type :ok, :f :append, :key "5", :value "x 44 10 y"} {:process 44, :type :invoke, :f :get, :key "2", :value nil} {:process 42, :type :ok, :f :append, :key "6", :value "x 42 11 y"} {:process 42, :type :invoke, :f :append, :key "3", :value "x 42 12 y"} {:process 22, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 y"} {:process 22, :type :invoke, :f :append, :key "9", :value "x 22 9 y"} {:process 28, :type :ok, :f :put, :key "8", :value "x 28 14 y"} {:process 28, :type :invoke, :f :append, :key "3", :value "x 28 15 y"} {:process 45, :type :ok, :f :append, :key "9", :value "x 45 4 y"} {:process 45, :type :invoke, :f :append, :key "4", :value "x 45 5 y"} {:process 24, :type :ok, :f :get, :key "8", :value "x 28 14 y"} {:process 24, :type :invoke, :f :get, :key "1", :value nil} {:process 15, :type :ok, :f :get, :key "4", :value "x 42 5 yx 49 21 yx 42 9 yx 39 12 y"} {:process 15, :type :invoke, :f :get, :key "8", :value nil} {:process 39, :type :ok, :f :put, :key "3", :value "x 39 13 y"} {:process 39, :type :invoke, :f :get, :key "0", :value nil} {:process 36, :type :ok, :f :append, :key "0", :value "x 36 7 y"} {:process 36, :type :invoke, :f :get, :key "2", :value nil} {:process 36, :type :ok, :f :get, :key "2", :value "x 45 2 yx 27 6 yx 13 9 yx 48 5 yx 12 9 yx 12 10 yx 23 9 yx 10 18 yx 10 20 y"} {:process 36, :type :invoke, :f :get, :key "7", :value nil} {:process 36, :type :ok, :f :get, :key "7", :value "x 12 11 yx 28 7 yx 22 4 yx 39 11 yx 42 10 y"} {:process 36, :type :invoke, :f :get, :key "6", :value nil} {:process 39, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 yx 42 7 yx 36 3 yx 10 19 yx 42 8 yx 36 4 yx 24 11 yx 3 14 yx 15 12 yx 36 7 y"} {:process 39, :type :invoke, :f :get, :key "8", :value nil} {:process 28, :type :ok, :f :append, :key "3", :value "x 28 15 y"} {:process 28, :type :invoke, :f :get, :key "4", :value nil} {:process 36, :type :ok, :f :get, :key "6", :value "x 9 1 yx 35 4 yx 3 11 yx 42 6 yx 3 15 yx 42 11 y"} {:process 36, :type :invoke, :f :get, :key "5", :value nil} {:process 45, :type :ok, :f :append, :key "4", :value "x 45 5 y"} {:process 45, :type :invoke, :f :get, :key "4", :value nil} {:process 45, :type :ok, :f :get, :key "4", :value "x 42 5 yx 49 21 yx 42 9 yx 39 12 yx 45 5 y"} {:process 45, :type :invoke, :f :append, :key "3", :value "x 45 6 y"} {:process 36, :type :ok, :f :get, :key "5", :value "x 39 10 yx 44 10 y"} {:process 36, :type :invoke, :f :append, :key "7", :value "x 36 8 y"} {:process 28, :type :ok, :f :get, :key "4", :value "x 42 5 yx 49 21 yx 42 9 yx 39 12 yx 45 5 y"} {:process 28, :type :invoke, :f :get, :key "5", :value nil} {:process 22, :type :ok, :f :append, :key "9", :value "x 22 9 y"} {:process 22, :type :invoke, :f :get, :key "9", :value nil} {:process 45, :type :ok, :f :append, :key "3", :value "x 45 6 y"} {:process 45, :type :invoke, :f :append, :key "0", :value "x 45 7 y"} {:process 39, :type :ok, :f :get, :key "8", :value "x 28 14 y"} {:process 39, :type :invoke, :f :append, :key "6", :value "x 39 14 y"} {:process 13, :type :ok, :f :append, :key "1", :value "x 13 11 y"} {:process 13, :type :invoke, :f :append, :key "9", :value "x 13 12 y"} {:process 25, :type :ok, :f :append, :key "4", :value "x 25 3 y"} {:process 25, :type :invoke, :f :get, :key "7", :value nil} {:process 22, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 y"} {:process 22, :type :invoke, :f :append, :key "4", :value "x 22 10 y"} {:process 0, :type :ok, :f :append, :key "5", :value "x 0 15 y"} {:process 0, :type :invoke, :f :append, :key "9", :value "x 0 16 y"} {:process 28, :type :ok, :f :get, :key "5", :value "x 39 10 yx 44 10 yx 0 15 y"} {:process 28, :type :invoke, :f :get, :key "2", :value nil} {:process 37, :type :ok, :f :append, :key "2", :value "x 37 6 y"} {:process 37, :type :invoke, :f :get, :key "9", :value nil} {:process 36, :type :ok, :f :append, :key "7", :value "x 36 8 y"} {:process 36, :type :invoke, :f :append, :key "0", :value "x 36 9 y"} {:process 39, :type :ok, :f :append, :key "6", :value "x 39 14 y"} {:process 39, :type :invoke, :f :get, :key "9", :value nil} {:process 45, :type :ok, :f :append, :key "0", :value "x 45 7 y"} {:process 45, :type :invoke, :f :append, :key "6", :value "x 45 8 y"} {:process 27, :type :ok, :f :append, :key "9", :value "x 27 10 y"} {:process 27, :type :invoke, :f :get, :key "8", :value nil} {:process 13, :type :ok, :f :append, :key "9", :value "x 13 12 y"} {:process 13, :type :invoke, :f :append, :key "0", :value "x 13 13 y"} {:process 22, :type :ok, :f :append, :key "4", :value "x 22 10 y"} {:process 22, :type :invoke, :f :append, :key "8", :value "x 22 11 y"} {:process 39, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 y"} {:process 39, :type :invoke, :f :append, :key "1", :value "x 39 15 y"} {:process 37, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 y"} {:process 37, :type :invoke, :f :get, :key "4", :value nil} {:process 37, :type :ok, :f :get, :key "4", :value "x 42 5 yx 49 21 yx 42 9 yx 39 12 yx 45 5 yx 25 3 yx 22 10 y"} {:process 37, :type :invoke, :f :get, :key "7", :value nil} {:process 28, :type :ok, :f :get, :key "2", :value "x 45 2 yx 27 6 yx 13 9 yx 48 5 yx 12 9 yx 12 10 yx 23 9 yx 10 18 yx 10 20 yx 37 6 y"} {:process 28, :type :invoke, :f :get, :key "1", :value nil} {:process 37, :type :ok, :f :get, :key "7", :value "x 12 11 yx 28 7 yx 22 4 yx 39 11 yx 42 10 yx 36 8 y"} {:process 37, :type :invoke, :f :append, :key "2", :value "x 37 7 y"} {:process 36, :type :ok, :f :append, :key "0", :value "x 36 9 y"} {:process 36, :type :invoke, :f :append, :key "0", :value "x 36 10 y"} {:process 0, :type :ok, :f :append, :key "9", :value "x 0 16 y"} {:process 0, :type :invoke, :f :get, :key "0", :value nil} {:process 0, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 yx 42 7 yx 36 3 yx 10 19 yx 42 8 yx 36 4 yx 24 11 yx 3 14 yx 15 12 yx 36 7 yx 45 7 yx 36 9 y"} {:process 0, :type :invoke, :f :append, :key "5", :value "x 0 17 y"} {:process 3, :type :ok, :f :get, :key "1", :value "x 3 8 yx 31 3 yx 16 5 yx 48 2 yx 26 8 yx 30 16 y"} {:process 3, :type :invoke, :f :get, :key "0", :value nil} {:process 27, :type :ok, :f :get, :key "8", :value "x 28 14 y"} {:process 27, :type :invoke, :f :append, :key "8", :value "x 27 11 y"} {:process 44, :type :ok, :f :get, :key "2", :value "x 45 2 yx 27 6 yx 13 9 y"} {:process 44, :type :invoke, :f :append, :key "1", :value "x 44 11 y"} {:process 45, :type :ok, :f :append, :key "6", :value "x 45 8 y"} {:process 45, :type :invoke, :f :get, :key "5", :value nil} {:process 22, :type :ok, :f :append, :key "8", :value "x 22 11 y"} {:process 22, :type :invoke, :f :get, :key "2", :value nil} {:process 13, :type :ok, :f :append, :key "0", :value "x 13 13 y"} {:process 13, :type :invoke, :f :append, :key "1", :value "x 13 14 y"} {:process 37, :type :ok, :f :append, :key "2", :value "x 37 7 y"} {:process 37, :type :invoke, :f :append, :key "3", :value "x 37 8 y"} {:process 27, :type :ok, :f :append, :key "8", :value "x 27 11 y"} {:process 27, :type :invoke, :f :append, :key "4", :value "x 27 12 y"} {:process 36, :type :ok, :f :append, :key "0", :value "x 36 10 y"} {:process 36, :type :invoke, :f :append, :key "1", :value "x 36 11 y"} {:process 39, :type :ok, :f :append, :key "1", :value "x 39 15 y"} {:process 39, :type :invoke, :f :get, :key "1", :value nil} {:process 39, :type :ok, :f :get, :key "1", :value "x 28 12 yx 13 11 yx 39 15 y"} {:process 39, :type :invoke, :f :append, :key "3", :value "x 39 16 y"} {:process 15, :type :ok, :f :get, :key "8", :value "x 47 5 yx 10 5 yx 18 8 yx 39 3 yx 6 16 yx 17 10 yx 0 8 yx 28 5 yx 43 5 yx 24 9 yx 13 8 y"} {:process 15, :type :invoke, :f :append, :key "6", :value "x 15 14 y"} {:process 0, :type :ok, :f :append, :key "5", :value "x 0 17 y"} {:process 0, :type :invoke, :f :get, :key "6", :value nil} {:process 24, :type :ok, :f :get, :key "1", :value "x 28 12 yx 13 11 yx 39 15 y"} {:process 24, :type :invoke, :f :append, :key "9", :value "x 24 12 y"} {:process 13, :type :ok, :f :append, :key "1", :value "x 13 14 y"} {:process 13, :type :invoke, :f :append, :key "6", :value "x 13 15 y"} {:process 37, :type :ok, :f :append, :key "3", :value "x 37 8 y"} {:process 37, :type :invoke, :f :append, :key "0", :value "x 37 9 y"} {:process 27, :type :ok, :f :append, :key "4", :value "x 27 12 y"} {:process 27, :type :invoke, :f :get, :key "0", :value nil} {:process 37, :type :ok, :f :append, :key "0", :value "x 37 9 y"} {:process 37, :type :invoke, :f :get, :key "9", :value nil} {:process 36, :type :ok, :f :append, :key "1", :value "x 36 11 y"} {:process 36, :type :invoke, :f :append, :key "6", :value "x 36 12 y"} {:process 39, :type :ok, :f :append, :key "3", :value "x 39 16 y"} {:process 39, :type :invoke, :f :append, :key "3", :value "x 39 17 y"} {:process 27, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 yx 42 7 yx 36 3 yx 10 19 yx 42 8 yx 36 4 yx 24 11 yx 3 14 yx 15 12 yx 36 7 yx 45 7 yx 36 9 yx 13 13 yx 36 10 yx 37 9 y"} {:process 27, :type :invoke, :f :get, :key "4", :value nil} {:process 13, :type :ok, :f :append, :key "6", :value "x 13 15 y"} {:process 13, :type :invoke, :f :get, :key "5", :value nil} {:process 10, :type :ok, :f :get, :key "6", :value "x 9 1 yx 35 4 yx 3 11 yx 42 6 yx 3 15 yx 42 11 yx 39 14 yx 45 8 y"} {:process 10, :type :invoke, :f :append, :key "6", :value "x 10 21 y"} {:process 25, :type :ok, :f :get, :key "7", :value "x 16 3 y"} {:process 25, :type :invoke, :f :get, :key "9", :value nil} {:process 27, :type :ok, :f :get, :key "4", :value "x 42 5 yx 49 21 yx 42 9 yx 39 12 yx 45 5 yx 25 3 yx 22 10 yx 27 12 y"} {:process 27, :type :invoke, :f :append, :key "4", :value "x 27 13 y"} {:process 7, :type :ok, :f :append, :key "9", :value "x 7 5 y"} {:process 7, :type :invoke, :f :append, :key "4", :value "x 7 6 y"} {:process 13, :type :ok, :f :get, :key "5", :value "x 39 10 yx 44 10 yx 0 15 yx 0 17 y"} {:process 13, :type :invoke, :f :append, :key "2", :value "x 13 16 y"} {:process 25, :type :ok, :f :get, :key "9", :value "x 6 2 yx 13 0 yx 36 0 yx 3 0 yx 24 0 yx 49 2 yx 18 0 yx 18 1 yx 5 1 yx 21 0 yx 18 4 yx 18 6 yx 41 0 yx 8 2 yx 17 4 yx 20 5 yx 42 1 yx 24 4 yx 11 14 yx 11 15 y"} {:process 25, :type :invoke, :f :append, :key "7", :value "x 25 4 y"} {:process 39, :type :ok, :f :append, :key "3", :value "x 39 17 y"} {:process 39, :type :invoke, :f :get, :key "0", :value nil} {:process 28, :type :ok, :f :get, :key "1", :value "x 28 12 yx 13 11 yx 39 15 yx 13 14 yx 36 11 y"} {:process 28, :type :invoke, :f :append, :key "3", :value "x 28 16 y"} {:process 39, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 yx 42 7 yx 36 3 yx 10 19 yx 42 8 yx 36 4 yx 24 11 yx 3 14 yx 15 12 yx 36 7 yx 45 7 yx 36 9 yx 13 13 yx 36 10 yx 37 9 y"} {:process 39, :type :invoke, :f :append, :key "5", :value "x 39 18 y"} {:process 22, :type :ok, :f :get, :key "2", :value "x 45 2 yx 27 6 yx 13 9 yx 48 5 yx 12 9 yx 12 10 yx 23 9 yx 10 18 yx 10 20 yx 37 6 yx 37 7 y"} {:process 22, :type :invoke, :f :append, :key "7", :value "x 22 12 y"} {:process 37, :type :ok, :f :get, :key "9", :value "x 31 7 yx 28 4 yx 0 13 yx 27 10 yx 25 2 y"} {:process 37, :type :invoke, :f :append, :key "1", :value "x 37 10 y"} {:process 0, :type :ok, :f :get, :key "6", :value "x 9 1 yx 35 4 yx 3 11 yx 42 6 yx 3 15 yx 42 11 yx 39 14 yx 45 8 yx 13 15 yx 36 12 y"} {:process 0, :type :invoke, :f :get, :key "1", :value nil} {:process 45, :type :ok, :f :get, :key "5", :value "x 39 10 yx 44 10 yx 0 15 yx 0 17 y"} {:process 45, :type :invoke, :f :append, :key "9", :value "x 45 9 y"} {:process 3, :type :ok, :f :get, :key "0", :value "x 15 8 yx 32 0 yx 33 1 yx 20 2 yx 1 3 yx 2 3 yx 11 3 yx 40 1 yx 0 5 yx 46 4 yx 26 2 yx 12 7 yx 11 8 yx 36 1 yx 45 1 yx 16 6 yx 16 7 y"} {:process 3, :type :invoke, :f :get, :key "7", :value nil} {:process 0, :type :ok, :f :get, :key "1", :value "x 28 12 yx 13 11 yx 39 15 yx 13 14 yx 36 11 y"} {:process 0, :type :invoke, :f :append, :key "7", :value "x 0 18 y"} {:process 3, :type :ok, :f :get, :key "7", :value "x 12 11 yx 28 7 yx 22 4 yx 39 11 yx 42 10 yx 36 8 y"} {:process 3, :type :invoke, :f :append, :key "2", :value "x 3 16 y"} {:process 32, :type :ok, :f :append, :key "0", :value "x 32 5 y"} {:process 32, :type :invoke, :f :append, :key "6", :value "x 32 6 y"} {:process 10, :type :ok, :f :append, :key "6", :value "x 10 21 y"} {:process 10, :type :invoke, :f :append, :key "8", :value "x 10 22 y"} {:process 32, :type :ok, :f :append, :key "6", :value "x 32 6 y"} {:process 32, :type :invoke, :f :get, :key "1", :value nil} {:process 32, :type :ok, :f :get, :key "1", :value "x 28 12 yx 13 11 yx 39 15 yx 13 14 yx 36 11 y"} {:process 32, :type :invoke, :f :get, :key "7", :value nil} {:process 25, :type :ok, :f :append, :key "7", :value "x 25 4 y"} {:process 25, :type :invoke, :f :append, :key "2", :value "x 25 5 y"} {:process 44, :type :ok, :f :append, :key "1", :value "x 44 11 y"} {:process 44, :type :invoke, :f :append, :key "4", :value "x 44 12 y"} {:process 14, :type :ok, :f :append, :key "5", :value "x 14 2 y"} {:process 14, :type :invoke, :f :get, :key "8", :value nil} {:process 22, :type :ok, :f :append, :key "7", :value "x 22 12 y"} {:process 22, :type :invoke, :f :append, :key "1", :value "x 22 13 y"} {:process 15, :type :ok, :f :append, :key "6", :value "x 15 14 y"} {:process 15, :type :invoke, :f :append, :key "9", :value "x 15 15 y"} {:process 25, :type :ok, :f :append, :key "2", :value "x 25 5 y"} {:process 25, :type :invoke, :f :get, :key "7", :value nil} {:process 14, :type :ok, :f :get, :key "8", :value "x 28 14 yx 22 11 yx 27 11 yx 10 22 y"} {:process 14, :type :invoke, :f :append, :key "8", :value "x 14 3 y"} {:process 44, :type :ok, :f :append, :key "4", :value "x 44 12 y"} {:process 44, :type :invoke, :f :append, :key "4", :value "x 44 13 y"} {:process 15, :type :ok, :f :append, :key "9", :value "x 15 15 y"} {:process 15, :type :invoke, :f :get, :key "3", :value nil} {:process 25, :type :ok, :f :get, :key "7", :value "x 12 11 yx 28 7 yx 22 4 yx 39 11 yx 42 10 yx 36 8 yx 5 6 yx 25 4 yx 22 12 y"} {:process 25, :type :invoke, :f :get, :key "5", :value nil} {:process 25, :type :ok, :f :get, :key "5", :value "x 39 10 yx 44 10 yx 0 15 yx 0 17 yx 39 18 y"} {:process 25, :type :invoke, :f :get, :key "6", :value nil} {:process 14, :type :ok, :f :append, :key "8", :value "x 14 3 y"} {:process 14, :type :invoke, :f :get, :key "9", :value nil} {:process 25, :type :ok, :f :get, :key "6", :value "x 9 1 yx 35 4 yx 3 11 yx 42 6 yx 3 15 yx 42 11 yx 39 14 yx 45 8 yx 13 15 yx 36 12 yx 10 21 yx 32 6 yx 15 14 y"} {:process 25, :type :invoke, :f :append, :key "8", :value "x 25 6 y"} {:process 14, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 yx 0 16 yx 7 5 yx 15 15 y"} {:process 14, :type :invoke, :f :append, :key "0", :value "x 14 4 y"} {:process 18, :type :ok, :f :append, :key "1", :value "x 18 9 y"} {:process 18, :type :invoke, :f :append, :key "2", :value "x 18 10 y"} {:process 15, :type :ok, :f :get, :key "3", :value "x 39 13 yx 28 15 yx 42 12 yx 45 6 yx 37 8 yx 39 16 yx 39 17 y"} {:process 15, :type :invoke, :f :append, :key "2", :value "x 15 16 y"} {:process 36, :type :ok, :f :append, :key "6", :value "x 36 12 y"} {:process 25, :type :ok, :f :append, :key "8", :value "x 25 6 y"} {:process 36, :type :invoke, :f :append, :key "5", :value "x 36 13 y"} {:process 25, :type :invoke, :f :append, :key "3", :value "x 25 7 y"} {:process 44, :type :ok, :f :append, :key "4", :value "x 44 13 y"} {:process 44, :type :invoke, :f :append, :key "2", :value "x 44 14 y"} {:process 4, :type :ok, :f :append, :key "8", :value "x 4 6 y"} {:process 4, :type :invoke, :f :append, :key "2", :value "x 4 7 y"} {:process 18, :type :ok, :f :append, :key "2", :value "x 18 10 y"} {:process 18, :type :invoke, :f :append, :key "6", :value "x 18 11 y"} {:process 14, :type :ok, :f :append, :key "0", :value "x 14 4 y"} {:process 14, :type :invoke, :f :get, :key "0", :value nil} {:process 25, :type :ok, :f :append, :key "3", :value "x 25 7 y"} {:process 25, :type :invoke, :f :get, :key "2", :value nil} {:process 14, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 yx 42 7 yx 36 3 yx 10 19 yx 42 8 yx 36 4 yx 24 11 yx 3 14 yx 15 12 yx 36 7 yx 45 7 yx 36 9 yx 13 13 yx 36 10 yx 37 9 yx 32 5 yx 14 4 y"} {:process 14, :type :invoke, :f :get, :key "7", :value nil} {:process 18, :type :ok, :f :append, :key "6", :value "x 18 11 y"} {:process 18, :type :invoke, :f :get, :key "3", :value nil} {:process 14, :type :ok, :f :get, :key "7", :value "x 12 11 yx 28 7 yx 22 4 yx 39 11 yx 42 10 yx 36 8 yx 5 6 yx 25 4 yx 22 12 y"} {:process 14, :type :invoke, :f :get, :key "1", :value nil} {:process 4, :type :ok, :f :append, :key "2", :value "x 4 7 y"} {:process 4, :type :invoke, :f :append, :key "7", :value "x 4 8 y"} {:process 25, :type :ok, :f :get, :key "2", :value "x 45 2 yx 27 6 yx 13 9 yx 48 5 yx 12 9 yx 12 10 yx 23 9 yx 10 18 yx 10 20 yx 37 6 yx 37 7 yx 13 16 yx 25 5 yx 18 10 yx 4 7 y"} {:process 25, :type :invoke, :f :put, :key "7", :value "x 25 8 y"} {:process 18, :type :ok, :f :get, :key "3", :value "x 39 13 yx 28 15 yx 42 12 yx 45 6 yx 37 8 yx 39 16 yx 39 17 yx 25 7 y"} {:process 18, :type :invoke, :f :put, :key "5", :value "x 18 12 y"} {:process 44, :type :ok, :f :append, :key "2", :value "x 44 14 y"} {:process 44, :type :invoke, :f :get, :key "8", :value nil} {:process 4, :type :ok, :f :append, :key "7", :value "x 4 8 y"} {:process 4, :type :invoke, :f :get, :key "0", :value nil} {:process 44, :type :ok, :f :get, :key "8", :value "x 28 14 yx 22 11 yx 27 11 yx 10 22 yx 14 3 yx 25 6 yx 4 6 y"} {:process 44, :type :invoke, :f :get, :key "4", :value nil} {:process 4, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 yx 42 7 yx 36 3 yx 10 19 yx 42 8 yx 36 4 yx 24 11 yx 3 14 yx 15 12 yx 36 7 yx 45 7 yx 36 9 yx 13 13 yx 36 10 yx 37 9 yx 32 5 yx 14 4 y"} {:process 4, :type :invoke, :f :put, :key "5", :value "x 4 9 y"} {:process 44, :type :ok, :f :get, :key "4", :value "x 42 5 yx 49 21 yx 42 9 yx 39 12 yx 45 5 yx 25 3 yx 22 10 yx 27 12 yx 7 6 yx 27 13 yx 44 12 yx 44 13 y"} {:process 44, :type :invoke, :f :append, :key "6", :value "x 44 15 y"} {:process 18, :type :ok, :f :put, :key "5", :value "x 18 12 y"} {:process 18, :type :invoke, :f :get, :key "0", :value nil} {:process 16, :type :ok, :f :append, :key "9", :value "x 16 11 y"} {:process 16, :type :invoke, :f :append, :key "0", :value "x 16 12 y"} {:process 25, :type :ok, :f :put, :key "7", :value "x 25 8 y"} {:process 25, :type :invoke, :f :append, :key "7", :value "x 25 9 y"} {:process 18, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 yx 42 7 yx 36 3 yx 10 19 yx 42 8 yx 36 4 yx 24 11 yx 3 14 yx 15 12 yx 36 7 yx 45 7 yx 36 9 yx 13 13 yx 36 10 yx 37 9 yx 32 5 yx 14 4 y"} {:process 18, :type :invoke, :f :get, :key "5", :value nil} {:process 33, :type :ok, :f :append, :key "9", :value "x 33 3 y"} {:process 33, :type :invoke, :f :append, :key "5", :value "x 33 4 y"} {:process 4, :type :ok, :f :put, :key "5", :value "x 4 9 y"} {:process 4, :type :invoke, :f :append, :key "4", :value "x 4 10 y"} {:process 16, :type :ok, :f :append, :key "0", :value "x 16 12 y"} {:process 16, :type :invoke, :f :append, :key "7", :value "x 16 13 y"} {:process 18, :type :ok, :f :get, :key "5", :value "x 4 9 y"} {:process 18, :type :invoke, :f :append, :key "9", :value "x 18 13 y"} {:process 11, :type :ok, :f :append, :key "3", :value "x 11 17 y"} {:process 11, :type :invoke, :f :append, :key "6", :value "x 11 18 y"} {:process 28, :type :ok, :f :append, :key "3", :value "x 28 16 y"} {:process 28, :type :invoke, :f :put, :key "1", :value "x 28 17 y"} {:process 33, :type :ok, :f :append, :key "5", :value "x 33 4 y"} {:process 33, :type :invoke, :f :get, :key "6", :value nil} {:process 28, :type :ok, :f :put, :key "1", :value "x 28 17 y"} {:process 28, :type :invoke, :f :append, :key "0", :value "x 28 18 y"} {:process 11, :type :ok, :f :append, :key "6", :value "x 11 18 y"} {:process 11, :type :invoke, :f :put, :key "5", :value "x 11 19 y"} {:process 4, :type :ok, :f :append, :key "4", :value "x 4 10 y"} {:process 18, :type :ok, :f :append, :key "9", :value "x 18 13 y"} {:process 4, :type :invoke, :f :get, :key "3", :value nil} {:process 18, :type :invoke, :f :get, :key "7", :value nil} {:process 16, :type :ok, :f :append, :key "7", :value "x 16 13 y"} {:process 16, :type :invoke, :f :get, :key "0", :value nil} {:process 33, :type :ok, :f :get, :key "6", :value "x 9 1 yx 35 4 yx 3 11 yx 42 6 yx 3 15 yx 42 11 yx 39 14 yx 45 8 yx 13 15 yx 36 12 yx 10 21 yx 32 6 yx 15 14 yx 18 11 yx 11 18 y"} {:process 33, :type :invoke, :f :put, :key "8", :value "x 33 5 y"} {:process 28, :type :ok, :f :append, :key "0", :value "x 28 18 y"} {:process 28, :type :invoke, :f :append, :key "6", :value "x 28 19 y"} {:process 4, :type :ok, :f :get, :key "3", :value "x 39 13 yx 28 15 yx 42 12 yx 45 6 yx 37 8 yx 39 16 yx 39 17 yx 25 7 yx 28 16 y"} {:process 4, :type :invoke, :f :put, :key "0", :value "x 4 11 y"} {:process 33, :type :ok, :f :put, :key "8", :value "x 33 5 y"} {:process 33, :type :invoke, :f :get, :key "7", :value nil} {:process 47, :type :ok, :f :append, :key "3", :value "x 47 6 y"} {:process 47, :type :invoke, :f :put, :key "6", :value "x 47 7 y"} {:process 14, :type :ok, :f :get, :key "1", :value "x 28 17 y"} {:process 14, :type :invoke, :f :get, :key "4", :value nil} {:process 43, :type :ok, :f :append, :key "1", :value "x 43 6 y"} {:process 43, :type :invoke, :f :append, :key "0", :value "x 43 7 y"} {:process 11, :type :ok, :f :put, :key "5", :value "x 11 19 y"} {:process 11, :type :invoke, :f :get, :key "6", :value nil} {:process 40, :type :ok, :f :append, :key "9", :value "x 40 2 y"} {:process 40, :type :invoke, :f :append, :key "5", :value "x 40 3 y"} {:process 28, :type :ok, :f :append, :key "6", :value "x 28 19 y"} {:process 28, :type :invoke, :f :get, :key "0", :value nil} {:process 47, :type :ok, :f :put, :key "6", :value "x 47 7 y"} {:process 47, :type :invoke, :f :append, :key "6", :value "x 47 8 y"} {:process 14, :type :ok, :f :get, :key "4", :value "x 42 5 yx 49 21 yx 42 9 yx 39 12 yx 45 5 yx 25 3 yx 22 10 yx 27 12 yx 7 6 yx 27 13 yx 44 12 yx 44 13 yx 4 10 y"} {:process 14, :type :invoke, :f :get, :key "0", :value nil} {:process 11, :type :ok, :f :get, :key "6", :value "x 47 7 y"} {:process 11, :type :invoke, :f :append, :key "3", :value "x 11 20 y"} {:process 40, :type :ok, :f :append, :key "5", :value "x 40 3 y"} {:process 40, :type :invoke, :f :get, :key "0", :value nil} {:process 28, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 yx 42 7 yx 36 3 yx 10 19 yx 42 8 yx 36 4 yx 24 11 yx 3 14 yx 15 12 yx 36 7 yx 45 7 yx 36 9 yx 13 13 yx 36 10 yx 37 9 yx 32 5 yx 14 4 yx 2 9 yx 16 12 yx 28 18 y"} {:process 28, :type :invoke, :f :append, :key "7", :value "x 28 20 y"} {:process 43, :type :ok, :f :append, :key "0", :value "x 43 7 y"} {:process 43, :type :invoke, :f :append, :key "9", :value "x 43 8 y"} {:process 40, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 yx 42 7 yx 36 3 yx 10 19 yx 42 8 yx 36 4 yx 24 11 yx 3 14 yx 15 12 yx 36 7 yx 45 7 yx 36 9 yx 13 13 yx 36 10 yx 37 9 yx 32 5 yx 14 4 yx 2 9 yx 16 12 yx 28 18 yx 43 7 y"} {:process 40, :type :invoke, :f :append, :key "1", :value "x 40 4 y"} {:process 14, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 yx 42 7 yx 36 3 yx 10 19 yx 42 8 yx 36 4 yx 24 11 yx 3 14 yx 15 12 yx 36 7 yx 45 7 yx 36 9 yx 13 13 yx 36 10 yx 37 9 yx 32 5 yx 14 4 yx 2 9 yx 16 12 yx 28 18 y"} {:process 14, :type :invoke, :f :append, :key "7", :value "x 14 5 y"} {:process 47, :type :ok, :f :append, :key "6", :value "x 47 8 y"} {:process 47, :type :invoke, :f :put, :key "2", :value "x 47 9 y"} {:process 28, :type :ok, :f :append, :key "7", :value "x 28 20 y"} {:process 40, :type :ok, :f :append, :key "1", :value "x 40 4 y"} {:process 28, :type :invoke, :f :append, :key "9", :value "x 28 21 y"} {:process 40, :type :invoke, :f :append, :key "0", :value "x 40 5 y"} {:process 47, :type :ok, :f :put, :key "2", :value "x 47 9 y"} {:process 47, :type :invoke, :f :append, :key "8", :value "x 47 10 y"} {:process 43, :type :ok, :f :append, :key "9", :value "x 43 8 y"} {:process 43, :type :invoke, :f :append, :key "8", :value "x 43 9 y"} {:process 0, :type :ok, :f :append, :key "7", :value "x 0 18 y"} {:process 0, :type :invoke, :f :get, :key "9", :value nil} {:process 32, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 y"} {:process 32, :type :invoke, :f :append, :key "9", :value "x 32 7 y"} {:process 16, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 yx 42 7 yx 36 3 yx 10 19 yx 42 8 yx 36 4 yx 24 11 yx 3 14 yx 15 12 yx 36 7 yx 45 7 yx 36 9 yx 13 13 yx 36 10 yx 37 9 yx 32 5 yx 14 4 yx 2 9 yx 16 12 yx 28 18 yx 43 7 y"} {:process 16, :type :invoke, :f :append, :key "4", :value "x 16 14 y"} {:process 47, :type :ok, :f :append, :key "8", :value "x 47 10 y"} {:process 47, :type :invoke, :f :get, :key "5", :value nil} {:process 28, :type :ok, :f :append, :key "9", :value "x 28 21 y"} {:process 28, :type :invoke, :f :append, :key "2", :value "x 28 22 y"} {:process 47, :type :ok, :f :get, :key "5", :value "x 11 19 yx 40 3 y"} {:process 47, :type :invoke, :f :append, :key "1", :value "x 47 11 y"} {:process 37, :type :ok, :f :append, :key "1", :value "x 37 10 y"} {:process 40, :type :ok, :f :append, :key "0", :value "x 40 5 y"} {:process 37, :type :invoke, :f :get, :key "3", :value nil} {:process 40, :type :invoke, :f :append, :key "1", :value "x 40 6 y"} {:process 0, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 yx 0 16 yx 7 5 yx 15 15 yx 33 3 yx 18 13 yx 40 2 yx 43 8 yx 28 21 y"} {:process 0, :type :invoke, :f :append, :key "3", :value "x 0 19 y"} {:process 43, :type :ok, :f :append, :key "8", :value "x 43 9 y"} {:process 43, :type :invoke, :f :append, :key "8", :value "x 43 10 y"} {:process 18, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 y"} {:process 18, :type :invoke, :f :get, :key "2", :value nil} {:process 18, :type :ok, :f :get, :key "2", :value "x 47 9 y"} {:process 18, :type :invoke, :f :get, :key "0", :value nil} {:process 28, :type :ok, :f :append, :key "2", :value "x 28 22 y"} {:process 28, :type :invoke, :f :get, :key "3", :value nil} {:process 33, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 y"} {:process 33, :type :invoke, :f :get, :key "7", :value nil} {:process 33, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 y"} {:process 33, :type :invoke, :f :get, :key "3", :value nil} {:process 47, :type :ok, :f :append, :key "1", :value "x 47 11 y"} {:process 47, :type :invoke, :f :append, :key "8", :value "x 47 12 y"} {:process 28, :type :ok, :f :get, :key "3", :value "x 39 13 yx 28 15 yx 42 12 yx 45 6 yx 37 8 yx 39 16 yx 39 17 yx 25 7 yx 28 16 yx 47 6 yx 0 19 y"} {:process 28, :type :invoke, :f :append, :key "7", :value "x 28 23 y"} {:process 18, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 yx 42 7 yx 36 3 yx 10 19 yx 42 8 yx 36 4 yx 24 11 yx 3 14 yx 15 12 yx 36 7 yx 45 7 yx 36 9 yx 13 13 yx 36 10 yx 37 9 yx 32 5 yx 14 4 yx 2 9 yx 16 12 yx 28 18 yx 43 7 yx 40 5 y"} {:process 18, :type :invoke, :f :get, :key "7", :value nil} {:process 26, :type :ok, :f :append, :key "4", :value "x 26 11 y"} {:process 26, :type :invoke, :f :append, :key "2", :value "x 26 12 y"} {:process 43, :type :ok, :f :append, :key "8", :value "x 43 10 y"} {:process 43, :type :invoke, :f :append, :key "8", :value "x 43 11 y"} {:process 18, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 y"} {:process 18, :type :invoke, :f :get, :key "5", :value nil} {:process 33, :type :ok, :f :get, :key "3", :value "x 39 13 yx 28 15 yx 42 12 yx 45 6 yx 37 8 yx 39 16 yx 39 17 yx 25 7 yx 28 16 yx 47 6 yx 0 19 y"} {:process 33, :type :invoke, :f :get, :key "3", :value nil} {:process 18, :type :ok, :f :get, :key "5", :value "x 11 19 yx 40 3 y"} {:process 18, :type :invoke, :f :append, :key "8", :value "x 18 14 y"} {:process 33, :type :ok, :f :get, :key "3", :value "x 39 13 yx 28 15 yx 42 12 yx 45 6 yx 37 8 yx 39 16 yx 39 17 yx 25 7 yx 28 16 yx 47 6 yx 0 19 y"} {:process 33, :type :invoke, :f :append, :key "6", :value "x 33 6 y"} {:process 26, :type :ok, :f :append, :key "2", :value "x 26 12 y"} {:process 26, :type :invoke, :f :append, :key "2", :value "x 26 13 y"} {:process 28, :type :ok, :f :append, :key "7", :value "x 28 23 y"} {:process 28, :type :invoke, :f :get, :key "4", :value nil} {:process 47, :type :ok, :f :append, :key "8", :value "x 47 12 y"} {:process 47, :type :invoke, :f :get, :key "8", :value nil} {:process 26, :type :ok, :f :append, :key "2", :value "x 26 13 y"} {:process 26, :type :invoke, :f :get, :key "1", :value nil} {:process 43, :type :ok, :f :append, :key "8", :value "x 43 11 y"} {:process 43, :type :invoke, :f :append, :key "6", :value "x 43 12 y"} {:process 39, :type :ok, :f :append, :key "5", :value "x 39 18 y"} {:process 39, :type :invoke, :f :get, :key "4", :value nil} {:process 28, :type :ok, :f :get, :key "4", :value "x 42 5 yx 49 21 yx 42 9 yx 39 12 yx 45 5 yx 25 3 yx 22 10 yx 27 12 yx 7 6 yx 27 13 yx 44 12 yx 44 13 yx 4 10 y"} {:process 28, :type :invoke, :f :get, :key "1", :value nil} {:process 47, :type :ok, :f :get, :key "8", :value "x 33 5 yx 47 10 yx 43 9 yx 43 10 yx 47 12 yx 43 11 y"} {:process 47, :type :invoke, :f :get, :key "1", :value nil} {:process 43, :type :ok, :f :append, :key "6", :value "x 43 12 y"} {:process 43, :type :invoke, :f :put, :key "4", :value "x 43 13 y"} {:process 41, :type :ok, :f :append, :key "5", :value "x 41 4 y"} {:process 41, :type :invoke, :f :get, :key "6", :value nil} {:process 37, :type :ok, :f :get, :key "3", :value "x 39 13 yx 28 15 yx 42 12 yx 45 6 yx 37 8 yx 39 16 yx 39 17 yx 25 7 yx 28 16 yx 47 6 yx 0 19 y"} {:process 37, :type :invoke, :f :append, :key "1", :value "x 37 11 y"} {:process 41, :type :ok, :f :get, :key "6", :value "x 47 7 yx 47 8 yx 43 12 y"} {:process 41, :type :invoke, :f :get, :key "9", :value nil} {:process 43, :type :ok, :f :put, :key "4", :value "x 43 13 y"} {:process 43, :type :invoke, :f :append, :key "3", :value "x 43 14 y"} {:process 41, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 yx 0 16 yx 7 5 yx 15 15 yx 33 3 yx 18 13 yx 40 2 yx 43 8 yx 28 21 y"} {:process 41, :type :invoke, :f :append, :key "0", :value "x 41 5 y"} {:process 6, :type :ok, :f :append, :key "6", :value "x 6 17 y"} {:process 6, :type :invoke, :f :get, :key "5", :value nil} {:process 9, :type :ok, :f :put, :key "6", :value "x 9 1 y"} {:process 9, :type :invoke, :f :get, :key "6", :value nil} {:process 41, :type :ok, :f :append, :key "0", :value "x 41 5 y"} {:process 41, :type :invoke, :f :get, :key "5", :value nil} {:process 41, :type :ok, :f :get, :key "5", :value "x 11 19 yx 40 3 yx 41 4 y"} {:process 41, :type :invoke, :f :get, :key "8", :value nil} {:process 6, :type :ok, :f :get, :key "5", :value "x 11 19 yx 40 3 yx 41 4 y"} {:process 6, :type :invoke, :f :append, :key "4", :value "x 6 18 y"} {:process 43, :type :ok, :f :append, :key "3", :value "x 43 14 y"} {:process 43, :type :invoke, :f :get, :key "7", :value nil} {:process 43, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 yx 28 23 y"} {:process 43, :type :invoke, :f :get, :key "5", :value nil} {:process 28, :type :ok, :f :get, :key "1", :value "x 28 17 yx 40 4 yx 37 10 yx 40 6 yx 47 11 y"} {:process 28, :type :invoke, :f :append, :key "1", :value "x 28 24 y"} {:process 41, :type :ok, :f :get, :key "8", :value "x 33 5 yx 47 10 yx 43 9 yx 43 10 yx 47 12 yx 43 11 y"} {:process 41, :type :invoke, :f :get, :key "4", :value nil} {:process 21, :type :ok, :f :append, :key "2", :value "x 21 8 y"} {:process 21, :type :invoke, :f :append, :key "9", :value "x 21 9 y"} {:process 6, :type :ok, :f :append, :key "4", :value "x 6 18 y"} {:process 6, :type :invoke, :f :append, :key "6", :value "x 6 19 y"} {:process 26, :type :ok, :f :get, :key "1", :value "x 28 17 yx 40 4 yx 37 10 yx 40 6 yx 47 11 y"} {:process 26, :type :invoke, :f :get, :key "4", :value nil} {:process 42, :type :ok, :f :append, :key "3", :value "x 42 12 y"} {:process 42, :type :invoke, :f :get, :key "7", :value nil} {:process 48, :type :ok, :f :append, :key "2", :value "x 48 5 y"} {:process 48, :type :invoke, :f :append, :key "4", :value "x 48 6 y"} {:process 41, :type :ok, :f :get, :key "4", :value "x 43 13 yx 6 18 y"} {:process 41, :type :invoke, :f :append, :key "8", :value "x 41 6 y"} {:process 21, :type :ok, :f :append, :key "9", :value "x 21 9 y"} {:process 21, :type :invoke, :f :append, :key "2", :value "x 21 10 y"} {:process 42, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 yx 28 23 y"} {:process 42, :type :invoke, :f :get, :key "7", :value nil} {:process 39, :type :ok, :f :get, :key "4", :value "x 43 13 yx 6 18 y"} {:process 39, :type :invoke, :f :append, :key "1", :value "x 39 19 y"} {:process 26, :type :ok, :f :get, :key "4", :value "x 43 13 y"} {:process 26, :type :invoke, :f :append, :key "3", :value "x 26 14 y"} {:process 6, :type :ok, :f :append, :key "6", :value "x 6 19 y"} {:process 6, :type :invoke, :f :put, :key "8", :value "x 6 20 y"} {:process 41, :type :ok, :f :append, :key "8", :value "x 41 6 y"} {:process 41, :type :invoke, :f :append, :key "9", :value "x 41 7 y"} {:process 42, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 yx 28 23 y"} {:process 42, :type :invoke, :f :append, :key "9", :value "x 42 13 y"} {:process 48, :type :ok, :f :append, :key "4", :value "x 48 6 y"} {:process 48, :type :invoke, :f :append, :key "9", :value "x 48 7 y"} {:process 49, :type :ok, :f :append, :key "4", :value "x 49 21 y"} {:process 49, :type :invoke, :f :append, :key "4", :value "x 49 22 y"} {:process 6, :type :ok, :f :put, :key "8", :value "x 6 20 y"} {:process 6, :type :invoke, :f :get, :key "8", :value nil} {:process 21, :type :ok, :f :append, :key "2", :value "x 21 10 y"} {:process 21, :type :invoke, :f :append, :key "9", :value "x 21 11 y"} {:process 41, :type :ok, :f :append, :key "9", :value "x 41 7 y"} {:process 41, :type :invoke, :f :get, :key "7", :value nil} {:process 13, :type :ok, :f :append, :key "2", :value "x 13 16 y"} {:process 13, :type :invoke, :f :append, :key "6", :value "x 13 17 y"} {:process 42, :type :ok, :f :append, :key "9", :value "x 42 13 y"} {:process 42, :type :invoke, :f :append, :key "2", :value "x 42 14 y"} {:process 45, :type :ok, :f :append, :key "9", :value "x 45 9 y"} {:process 45, :type :invoke, :f :get, :key "8", :value nil} {:process 9, :type :ok, :f :get, :key "6", :value "x 47 7 yx 47 8 yx 43 12 yx 6 19 y"} {:process 9, :type :invoke, :f :append, :key "9", :value "x 9 2 y"} {:process 41, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 yx 28 23 y"} {:process 41, :type :invoke, :f :get, :key "4", :value nil} {:process 41, :type :ok, :f :get, :key "4", :value "x 43 13 yx 6 18 yx 48 6 y"} {:process 41, :type :invoke, :f :get, :key "6", :value nil} {:process 21, :type :ok, :f :append, :key "9", :value "x 21 11 y"} {:process 21, :type :invoke, :f :append, :key "3", :value "x 21 12 y"} {:process 45, :type :ok, :f :get, :key "8", :value "x 6 20 y"} {:process 45, :type :invoke, :f :get, :key "1", :value nil} {:process 43, :type :ok, :f :get, :key "5", :value "x 39 10 yx 44 10 yx 0 15 yx 0 17 y"} {:process 43, :type :invoke, :f :append, :key "5", :value "x 43 15 y"} {:process 41, :type :ok, :f :get, :key "6", :value "x 47 7 yx 47 8 yx 43 12 yx 6 19 y"} {:process 41, :type :invoke, :f :append, :key "1", :value "x 41 8 y"} {:process 8, :type :ok, :f :append, :key "1", :value "x 8 15 y"} {:process 8, :type :invoke, :f :append, :key "2", :value "x 8 16 y"} {:process 42, :type :ok, :f :append, :key "2", :value "x 42 14 y"} {:process 42, :type :invoke, :f :put, :key "5", :value "x 42 15 y"} {:process 8, :type :ok, :f :append, :key "2", :value "x 8 16 y"} {:process 8, :type :invoke, :f :append, :key "9", :value "x 8 17 y"} {:process 42, :type :ok, :f :put, :key "5", :value "x 42 15 y"} {:process 41, :type :ok, :f :append, :key "1", :value "x 41 8 y"} {:process 42, :type :invoke, :f :append, :key "3", :value "x 42 16 y"} {:process 41, :type :invoke, :f :get, :key "0", :value nil} {:process 29, :type :ok, :f :append, :key "9", :value "x 29 6 y"} {:process 29, :type :invoke, :f :append, :key "5", :value "x 29 7 y"} {:process 41, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 yx 42 7 yx 36 3 yx 10 19 yx 42 8 yx 36 4 yx 24 11 yx 3 14 yx 15 12 yx 36 7 yx 45 7 yx 36 9 yx 13 13 yx 36 10 yx 37 9 yx 32 5 yx 14 4 yx 2 9 yx 16 12 yx 28 18 yx 43 7 yx 40 5 yx 41 5 y"} {:process 41, :type :invoke, :f :get, :key "3", :value nil} {:process 6, :type :ok, :f :get, :key "8", :value "x 6 20 y"} {:process 6, :type :invoke, :f :get, :key "0", :value nil} {:process 41, :type :ok, :f :get, :key "3", :value "x 39 13 yx 28 15 yx 42 12 yx 45 6 yx 37 8 yx 39 16 yx 39 17 yx 25 7 yx 28 16 yx 47 6 yx 0 19 yx 43 14 yx 21 12 y"} {:process 41, :type :invoke, :f :get, :key "1", :value nil} {:process 41, :type :ok, :f :get, :key "1", :value "x 28 17 yx 40 4 yx 37 10 yx 40 6 yx 47 11 yx 8 15 yx 41 8 y"} {:process 41, :type :invoke, :f :append, :key "6", :value "x 41 9 y"} {:process 6, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 yx 42 7 yx 36 3 yx 10 19 yx 42 8 yx 36 4 yx 24 11 yx 3 14 yx 15 12 yx 36 7 yx 45 7 yx 36 9 yx 13 13 yx 36 10 yx 37 9 yx 32 5 yx 14 4 yx 2 9 yx 16 12 yx 28 18 yx 43 7 yx 40 5 yx 41 5 y"} {:process 6, :type :invoke, :f :get, :key "9", :value nil} {:process 6, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 yx 0 16 yx 7 5 yx 15 15 yx 33 3 yx 18 13 yx 40 2 yx 43 8 yx 28 21 yx 21 9 yx 41 7 yx 42 13 yx 45 9 yx 48 7 yx 21 11 y"} {:process 6, :type :invoke, :f :get, :key "3", :value nil} {:process 6, :type :ok, :f :get, :key "3", :value "x 39 13 yx 28 15 yx 42 12 yx 45 6 yx 37 8 yx 39 16 yx 39 17 yx 25 7 yx 28 16 yx 47 6 yx 0 19 yx 43 14 yx 21 12 y"} {:process 6, :type :invoke, :f :get, :key "2", :value nil} {:process 45, :type :ok, :f :get, :key "1", :value "x 28 17 yx 40 4 yx 37 10 yx 40 6 yx 47 11 yx 8 15 y"} {:process 45, :type :invoke, :f :append, :key "7", :value "x 45 10 y"} {:process 6, :type :ok, :f :get, :key "2", :value "x 47 9 yx 28 22 yx 26 12 yx 26 13 yx 21 8 yx 21 10 yx 42 14 yx 8 16 y"} {:process 6, :type :invoke, :f :put, :key "3", :value "x 6 21 y"} {:process 47, :type :ok, :f :get, :key "1", :value "x 28 17 yx 40 4 yx 37 10 yx 40 6 yx 47 11 yx 8 15 y"} {:process 47, :type :invoke, :f :append, :key "8", :value "x 47 13 y"} {:process 35, :type :ok, :f :append, :key "6", :value "x 35 5 y"} {:process 35, :type :invoke, :f :append, :key "5", :value "x 35 6 y"} {:process 18, :type :ok, :f :append, :key "8", :value "x 18 14 y"} {:process 18, :type :invoke, :f :get, :key "6", :value nil} {:process 18, :type :ok, :f :get, :key "6", :value "x 47 7 yx 47 8 yx 43 12 yx 6 19 yx 13 17 yx 35 5 y"} {:process 18, :type :invoke, :f :get, :key "0", :value nil} {:process 31, :type :ok, :f :append, :key "6", :value "x 31 9 y"} {:process 31, :type :invoke, :f :put, :key "5", :value "x 31 10 y"} {:process 35, :type :ok, :f :append, :key "5", :value "x 35 6 y"} {:process 35, :type :invoke, :f :append, :key "9", :value "x 35 7 y"} {:process 2, :type :ok, :f :append, :key "0", :value "x 2 9 y"} {:process 2, :type :invoke, :f :put, :key "8", :value "x 2 10 y"} {:process 18, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 yx 42 7 yx 36 3 yx 10 19 yx 42 8 yx 36 4 yx 24 11 yx 3 14 yx 15 12 yx 36 7 yx 45 7 yx 36 9 yx 13 13 yx 36 10 yx 37 9 yx 32 5 yx 14 4 yx 2 9 yx 16 12 yx 28 18 yx 43 7 yx 40 5 yx 41 5 y"} {:process 18, :type :invoke, :f :put, :key "5", :value "x 18 15 y"} {:process 31, :type :ok, :f :put, :key "5", :value "x 31 10 y"} {:process 31, :type :invoke, :f :get, :key "2", :value nil} {:process 18, :type :ok, :f :put, :key "5", :value "x 18 15 y"} {:process 18, :type :invoke, :f :put, :key "2", :value "x 18 16 y"} {:process 31, :type :ok, :f :get, :key "2", :value "x 47 9 yx 28 22 yx 26 12 yx 26 13 yx 21 8 yx 21 10 yx 42 14 yx 8 16 y"} {:process 31, :type :invoke, :f :append, :key "1", :value "x 31 11 y"} {:process 2, :type :ok, :f :put, :key "8", :value "x 2 10 y"} {:process 2, :type :invoke, :f :append, :key "5", :value "x 2 11 y"} {:process 35, :type :ok, :f :append, :key "9", :value "x 35 7 y"} {:process 35, :type :invoke, :f :get, :key "6", :value nil} {:process 2, :type :ok, :f :append, :key "5", :value "x 2 11 y"} {:process 2, :type :invoke, :f :get, :key "5", :value nil} {:process 31, :type :ok, :f :append, :key "1", :value "x 31 11 y"} {:process 31, :type :invoke, :f :get, :key "5", :value nil} {:process 2, :type :ok, :f :get, :key "5", :value "x 18 15 yx 2 11 y"} {:process 2, :type :invoke, :f :append, :key "0", :value "x 2 12 y"} {:process 31, :type :ok, :f :get, :key "5", :value "x 18 15 yx 2 11 y"} {:process 31, :type :invoke, :f :get, :key "9", :value nil} {:process 23, :type :ok, :f :append, :key "9", :value "x 23 10 y"} {:process 23, :type :invoke, :f :append, :key "9", :value "x 23 11 y"} {:process 31, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 yx 0 16 yx 7 5 yx 15 15 yx 33 3 yx 18 13 yx 40 2 yx 43 8 yx 28 21 yx 21 9 yx 41 7 yx 42 13 yx 45 9 yx 48 7 yx 21 11 yx 35 7 yx 23 10 y"} {:process 31, :type :invoke, :f :append, :key "9", :value "x 31 12 y"} {:process 2, :type :ok, :f :append, :key "0", :value "x 2 12 y"} {:process 2, :type :invoke, :f :append, :key "7", :value "x 2 13 y"} {:process 12, :type :ok, :f :append, :key "0", :value "x 12 12 y"} {:process 12, :type :invoke, :f :get, :key "3", :value nil} {:process 2, :type :ok, :f :append, :key "7", :value "x 2 13 y"} {:process 2, :type :invoke, :f :get, :key "4", :value nil} {:process 12, :type :ok, :f :get, :key "3", :value "x 39 13 yx 28 15 yx 42 12 yx 45 6 yx 37 8 yx 39 16 yx 39 17 yx 25 7 yx 28 16 yx 47 6 yx 0 19 yx 43 14 yx 21 12 yx 17 12 y"} {:process 12, :type :invoke, :f :get, :key "7", :value nil} {:process 49, :type :ok, :f :append, :key "4", :value "x 49 22 y"} {:process 49, :type :invoke, :f :append, :key "0", :value "x 49 23 y"} {:process 2, :type :ok, :f :get, :key "4", :value "x 43 13 yx 6 18 yx 48 6 yx 49 22 y"} {:process 2, :type :invoke, :f :get, :key "8", :value nil} {:process 2, :type :ok, :f :get, :key "8", :value "x 2 10 y"} {:process 2, :type :invoke, :f :get, :key "6", :value nil} {:process 2, :type :ok, :f :get, :key "6", :value "x 47 7 yx 47 8 yx 43 12 yx 6 19 yx 13 17 yx 35 5 yx 31 9 y"} {:process 2, :type :invoke, :f :get, :key "7", :value nil} {:process 12, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 yx 28 23 yx 2 13 y"} {:process 12, :type :invoke, :f :get, :key "8", :value nil} {:process 31, :type :ok, :f :append, :key "9", :value "x 31 12 y"} {:process 31, :type :invoke, :f :append, :key "2", :value "x 31 13 y"} {:process 12, :type :ok, :f :get, :key "8", :value "x 2 10 y"} {:process 12, :type :invoke, :f :get, :key "9", :value nil} {:process 2, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 yx 28 23 yx 2 13 y"} {:process 2, :type :invoke, :f :get, :key "1", :value nil} {:process 31, :type :ok, :f :append, :key "2", :value "x 31 13 y"} {:process 31, :type :invoke, :f :put, :key "4", :value "x 31 14 y"} {:process 2, :type :ok, :f :get, :key "1", :value "x 28 17 yx 40 4 yx 37 10 yx 40 6 yx 47 11 yx 8 15 yx 41 8 yx 31 11 y"} {:process 2, :type :invoke, :f :append, :key "3", :value "x 2 14 y"} {:process 31, :type :ok, :f :put, :key "4", :value "x 31 14 y"} {:process 31, :type :invoke, :f :append, :key "9", :value "x 31 15 y"} {:process 10, :type :ok, :f :append, :key "8", :value "x 10 22 y"} {:process 10, :type :invoke, :f :append, :key "4", :value "x 10 23 y"} {:process 8, :type :ok, :f :append, :key "9", :value "x 8 17 y"} {:process 8, :type :invoke, :f :get, :key "7", :value nil} {:process 2, :type :ok, :f :append, :key "3", :value "x 2 14 y"} {:process 2, :type :invoke, :f :get, :key "7", :value nil} {:process 8, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 yx 28 23 yx 2 13 y"} {:process 8, :type :invoke, :f :get, :key "7", :value nil} {:process 2, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 yx 28 23 yx 2 13 y"} {:process 2, :type :invoke, :f :get, :key "6", :value nil} {:process 8, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 yx 28 23 yx 2 13 y"} {:process 8, :type :invoke, :f :get, :key "3", :value nil} {:process 31, :type :ok, :f :append, :key "9", :value "x 31 15 y"} {:process 31, :type :invoke, :f :append, :key "3", :value "x 31 16 y"} {:process 2, :type :ok, :f :get, :key "6", :value "x 47 7 yx 47 8 yx 43 12 yx 6 19 yx 13 17 yx 35 5 yx 31 9 y"} {:process 2, :type :invoke, :f :append, :key "2", :value "x 2 15 y"} {:process 8, :type :ok, :f :get, :key "3", :value "x 39 13 yx 28 15 yx 42 12 yx 45 6 yx 37 8 yx 39 16 yx 39 17 yx 25 7 yx 28 16 yx 47 6 yx 0 19 yx 43 14 yx 21 12 yx 17 12 yx 2 14 y"} {:process 8, :type :invoke, :f :get, :key "0", :value nil} {:process 31, :type :ok, :f :append, :key "3", :value "x 31 16 y"} {:process 31, :type :invoke, :f :get, :key "9", :value nil} {:process 2, :type :ok, :f :append, :key "2", :value "x 2 15 y"} {:process 2, :type :invoke, :f :append, :key "1", :value "x 2 16 y"} {:process 31, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 yx 0 16 yx 7 5 yx 15 15 yx 33 3 yx 18 13 yx 40 2 yx 43 8 yx 28 21 yx 21 9 yx 41 7 yx 42 13 yx 45 9 yx 48 7 yx 21 11 yx 35 7 yx 23 10 yx 31 12 yx 8 17 yx 31 15 y"} {:process 31, :type :invoke, :f :get, :key "4", :value nil} {:process 24, :type :ok, :f :append, :key "9", :value "x 24 12 y"} {:process 24, :type :invoke, :f :append, :key "8", :value "x 24 13 y"} {:process 35, :type :ok, :f :get, :key "6", :value "x 47 7 yx 47 8 yx 43 12 yx 6 19 yx 13 17 yx 35 5 yx 31 9 y"} {:process 35, :type :invoke, :f :get, :key "4", :value nil} {:process 31, :type :ok, :f :get, :key "4", :value "x 31 14 y"} {:process 31, :type :invoke, :f :get, :key "0", :value nil} {:process 24, :type :ok, :f :append, :key "8", :value "x 24 13 y"} {:process 24, :type :invoke, :f :append, :key "7", :value "x 24 14 y"} {:process 31, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 yx 42 7 yx 36 3 yx 10 19 yx 42 8 yx 36 4 yx 24 11 yx 3 14 yx 15 12 yx 36 7 yx 45 7 yx 36 9 yx 13 13 yx 36 10 yx 37 9 yx 32 5 yx 14 4 yx 2 9 yx 16 12 yx 28 18 yx 43 7 yx 40 5 yx 41 5 yx 2 12 yx 12 12 yx 49 23 y"} {:process 31, :type :invoke, :f :get, :key "7", :value nil} {:process 31, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 yx 28 23 yx 2 13 y"} {:process 31, :type :invoke, :f :append, :key "1", :value "x 31 17 y"} {:process 35, :type :ok, :f :get, :key "4", :value "x 31 14 y"} {:process 35, :type :invoke, :f :append, :key "7", :value "x 35 8 y"} {:process 15, :type :ok, :f :append, :key "2", :value "x 15 16 y"} {:process 15, :type :invoke, :f :get, :key "9", :value nil} {:process 24, :type :ok, :f :append, :key "7", :value "x 24 14 y"} {:process 24, :type :invoke, :f :get, :key "4", :value nil} {:process 15, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 yx 0 16 yx 7 5 yx 15 15 yx 33 3 yx 18 13 yx 40 2 yx 43 8 yx 28 21 yx 21 9 yx 41 7 yx 42 13 yx 45 9 yx 48 7 yx 21 11 yx 35 7 yx 23 10 yx 31 12 yx 8 17 yx 31 15 yx 24 12 y"} {:process 15, :type :invoke, :f :append, :key "1", :value "x 15 17 y"} {:process 24, :type :ok, :f :get, :key "4", :value "x 31 14 y"} {:process 24, :type :invoke, :f :append, :key "4", :value "x 24 15 y"} {:process 24, :type :ok, :f :append, :key "4", :value "x 24 15 y"} {:process 24, :type :invoke, :f :append, :key "9", :value "x 24 16 y"} {:process 43, :type :ok, :f :append, :key "5", :value "x 43 15 y"} {:process 43, :type :invoke, :f :append, :key "5", :value "x 43 16 y"} {:process 8, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 yx 42 7 yx 36 3 yx 10 19 yx 42 8 yx 36 4 yx 24 11 yx 3 14 yx 15 12 yx 36 7 yx 45 7 yx 36 9 yx 13 13 yx 36 10 yx 37 9 yx 32 5 yx 14 4 yx 2 9 yx 16 12 yx 28 18 yx 43 7 yx 40 5 yx 41 5 yx 2 12 yx 12 12 yx 49 23 y"} {:process 8, :type :invoke, :f :append, :key "1", :value "x 8 18 y"} {:process 24, :type :ok, :f :append, :key "9", :value "x 24 16 y"} {:process 24, :type :invoke, :f :append, :key "2", :value "x 24 17 y"} {:process 12, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 yx 0 16 yx 7 5 yx 15 15 yx 33 3 yx 18 13 yx 40 2 yx 43 8 yx 28 21 yx 21 9 yx 41 7 yx 42 13 yx 45 9 yx 48 7 yx 21 11 yx 35 7 yx 23 10 yx 31 12 yx 8 17 yx 31 15 yx 24 12 yx 24 16 y"} {:process 12, :type :invoke, :f :get, :key "2", :value nil} {:process 24, :type :ok, :f :append, :key "2", :value "x 24 17 y"} {:process 24, :type :invoke, :f :append, :key "2", :value "x 24 18 y"} {:process 12, :type :ok, :f :get, :key "2", :value "x 18 16 yx 31 13 yx 2 15 yx 15 16 y"} {:process 12, :type :invoke, :f :get, :key "0", :value nil} {:process 24, :type :ok, :f :append, :key "2", :value "x 24 18 y"} {:process 24, :type :invoke, :f :get, :key "1", :value nil} {:process 37, :type :ok, :f :append, :key "1", :value "x 37 11 y"} {:process 37, :type :invoke, :f :get, :key "6", :value nil} {:process 12, :type :ok, :f :get, :key "0", :value "x 25 1 yx 19 4 yx 1 7 yx 10 16 yx 42 7 yx 36 3 yx 10 19 yx 42 8 yx 36 4 yx 24 11 yx 3 14 yx 15 12 yx 36 7 yx 45 7 yx 36 9 yx 13 13 yx 36 10 yx 37 9 yx 32 5 yx 14 4 yx 2 9 yx 16 12 yx 28 18 yx 43 7 yx 40 5 yx 41 5 yx 2 12 yx 12 12 yx 49 23 y"} {:process 12, :type :invoke, :f :append, :key "3", :value "x 12 13 y"} {:process 24, :type :ok, :f :get, :key "1", :value "x 28 17 yx 40 4 yx 37 10 yx 40 6 yx 47 11 yx 8 15 yx 41 8 yx 31 11 yx 2 16 yx 15 17 yx 37 11 y"} {:process 24, :type :invoke, :f :append, :key "5", :value "x 24 19 y"} {:process 44, :type :ok, :f :append, :key "6", :value "x 44 15 y"} {:process 44, :type :invoke, :f :append, :key "6", :value "x 44 16 y"} {:process 24, :type :ok, :f :append, :key "5", :value "x 24 19 y"} {:process 24, :type :invoke, :f :append, :key "3", :value "x 24 20 y"} {:process 44, :type :ok, :f :append, :key "6", :value "x 44 16 y"} {:process 44, :type :invoke, :f :append, :key "2", :value "x 44 17 y"} {:process 37, :type :ok, :f :get, :key "6", :value "x 47 7 yx 47 8 yx 43 12 yx 6 19 yx 13 17 yx 35 5 yx 31 9 yx 44 15 yx 44 16 y"} {:process 37, :type :invoke, :f :get, :key "8", :value nil} {:process 14, :type :ok, :f :append, :key "7", :value "x 14 5 y"} {:process 14, :type :invoke, :f :append, :key "9", :value "x 14 6 y"} {:process 36, :type :ok, :f :append, :key "5", :value "x 36 13 y"} {:process 36, :type :invoke, :f :put, :key "1", :value "x 36 14 y"} {:process 44, :type :ok, :f :append, :key "2", :value "x 44 17 y"} {:process 44, :type :invoke, :f :append, :key "6", :value "x 44 18 y"} {:process 45, :type :ok, :f :append, :key "7", :value "x 45 10 y"} {:process 45, :type :invoke, :f :put, :key "5", :value "x 45 11 y"} {:process 37, :type :ok, :f :get, :key "8", :value "x 2 10 yx 24 13 y"} {:process 37, :type :invoke, :f :get, :key "6", :value nil} {:process 36, :type :ok, :f :put, :key "1", :value "x 36 14 y"} {:process 36, :type :invoke, :f :get, :key "4", :value nil} {:process 45, :type :ok, :f :put, :key "5", :value "x 45 11 y"} {:process 45, :type :invoke, :f :append, :key "7", :value "x 45 12 y"} {:process 24, :type :ok, :f :append, :key "3", :value "x 24 20 y"} {:process 24, :type :invoke, :f :get, :key "5", :value nil} {:process 36, :type :ok, :f :get, :key "4", :value "x 31 14 yx 24 15 y"} {:process 36, :type :invoke, :f :append, :key "4", :value "x 36 15 y"} {:process 37, :type :ok, :f :get, :key "6", :value "x 47 7 yx 47 8 yx 43 12 yx 6 19 yx 13 17 yx 35 5 yx 31 9 yx 44 15 yx 44 16 y"} {:process 37, :type :invoke, :f :get, :key "5", :value nil} {:process 37, :type :ok, :f :get, :key "5", :value "x 45 11 y"} {:process 37, :type :invoke, :f :append, :key "7", :value "x 37 12 y"} {:process 14, :type :ok, :f :append, :key "9", :value "x 14 6 y"} {:process 14, :type :invoke, :f :get, :key "4", :value nil} {:process 24, :type :ok, :f :get, :key "5", :value "x 45 11 y"} {:process 24, :type :invoke, :f :put, :key "0", :value "x 24 21 y"} {:process 14, :type :ok, :f :get, :key "4", :value "x 31 14 yx 24 15 y"} {:process 14, :type :invoke, :f :get, :key "7", :value nil} {:process 45, :type :ok, :f :append, :key "7", :value "x 45 12 y"} {:process 45, :type :invoke, :f :append, :key "4", :value "x 45 13 y"} {:process 14, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 yx 28 23 yx 2 13 yx 24 14 yx 14 5 yx 45 10 yx 45 12 y"} {:process 14, :type :invoke, :f :get, :key "2", :value nil} {:process 0, :type :ok, :f :append, :key "3", :value "x 0 19 y"} {:process 0, :type :invoke, :f :append, :key "1", :value "x 0 20 y"} {:process 14, :type :ok, :f :get, :key "2", :value "x 18 16 yx 31 13 yx 2 15 yx 15 16 yx 24 17 yx 24 18 yx 44 17 y"} {:process 14, :type :invoke, :f :get, :key "1", :value nil} {:process 14, :type :ok, :f :get, :key "1", :value "x 36 14 y"} {:process 14, :type :invoke, :f :get, :key "5", :value nil} {:process 45, :type :ok, :f :append, :key "4", :value "x 45 13 y"} {:process 45, :type :invoke, :f :get, :key "0", :value nil} {:process 19, :type :ok, :f :append, :key "0", :value "x 19 4 y"} {:process 19, :type :invoke, :f :append, :key "4", :value "x 19 5 y"} {:process 14, :type :ok, :f :get, :key "5", :value "x 45 11 y"} {:process 14, :type :invoke, :f :append, :key "2", :value "x 14 7 y"} {:process 25, :type :ok, :f :append, :key "7", :value "x 25 9 y"} {:process 25, :type :invoke, :f :append, :key "4", :value "x 25 10 y"} {:process 34, :type :ok, :f :append, :key "8", :value "x 34 3 y"} {:process 34, :type :invoke, :f :get, :key "1", :value nil} {:process 45, :type :ok, :f :get, :key "0", :value ""} {:process 34, :type :ok, :f :get, :key "1", :value ""} {:process 13, :type :ok, :f :append, :key "6", :value "x 13 17 y"} {:process 48, :type :ok, :f :append, :key "9", :value "x 48 7 y"} {:process 8, :type :ok, :f :append, :key "1", :value "x 8 18 y"} {:process 10, :type :ok, :f :append, :key "4", :value "x 10 23 y"} {:process 39, :type :ok, :f :append, :key "1", :value "x 39 19 y"} {:process 28, :type :ok, :f :append, :key "1", :value "x 28 24 y"} {:process 0, :type :ok, :f :append, :key "1", :value "x 0 20 y"} {:process 3, :type :ok, :f :append, :key "2", :value "x 3 16 y"} {:process 30, :type :ok, :f :append, :key "6", :value "x 30 18 y"} {:process 32, :type :ok, :f :append, :key "9", :value "x 32 7 y"} {:process 43, :type :ok, :f :append, :key "5", :value "x 43 16 y"} {:process 22, :type :ok, :f :append, :key "1", :value "x 22 13 y"} {:process 12, :type :ok, :f :append, :key "3", :value "x 12 13 y"} {:process 17, :type :ok, :f :append, :key "3", :value "x 17 12 y"} {:process 41, :type :ok, :f :append, :key "6", :value "x 41 9 y"} {:process 23, :type :ok, :f :append, :key "9", :value "x 23 11 y"} {:process 27, :type :ok, :f :append, :key "4", :value "x 27 13 y"} {:process 46, :type :ok, :f :append, :key "2", :value "x 46 6 y"} {:process 5, :type :ok, :f :append, :key "7", :value "x 5 6 y"} {:process 19, :type :ok, :f :append, :key "4", :value "x 19 5 y"} {:process 25, :type :ok, :f :append, :key "4", :value "x 25 10 y"} {:process 15, :type :ok, :f :append, :key "1", :value "x 15 17 y"} {:process 35, :type :ok, :f :append, :key "7", :value "x 35 8 y"} {:process 20, :type :ok, :f :append, :key "9", :value "x 20 9 y"} {:process 47, :type :ok, :f :append, :key "8", :value "x 47 13 y"} {:process 42, :type :ok, :f :append, :key "3", :value "x 42 16 y"} {:process 33, :type :ok, :f :append, :key "6", :value "x 33 6 y"} {:process 37, :type :ok, :f :append, :key "7", :value "x 37 12 y"} {:process 36, :type :ok, :f :append, :key "4", :value "x 36 15 y"} {:process 21, :type :ok, :f :append, :key "3", :value "x 21 12 y"} {:process 18, :type :ok, :f :put, :key "2", :value "x 18 16 y"} {:process 4, :type :ok, :f :put, :key "0", :value "x 4 11 y"} {:process 7, :type :ok, :f :append, :key "4", :value "x 7 6 y"} {:process 14, :type :ok, :f :append, :key "2", :value "x 14 7 y"} {:process 6, :type :ok, :f :put, :key "3", :value "x 6 21 y"} {:process 31, :type :ok, :f :append, :key "1", :value "x 31 17 y"} {:process 11, :type :ok, :f :append, :key "3", :value "x 11 20 y"} {:process 26, :type :ok, :f :append, :key "3", :value "x 26 14 y"} {:process 2, :type :ok, :f :append, :key "1", :value "x 2 16 y"} {:process 49, :type :ok, :f :append, :key "0", :value "x 49 23 y"} {:process 29, :type :ok, :f :append, :key "5", :value "x 29 7 y"} {:process 9, :type :ok, :f :append, :key "9", :value "x 9 2 y"} {:process 1, :type :ok, :f :append, :key "0", :value "x 1 7 y"} {:process 38, :type :ok, :f :append, :key "4", :value "x 38 0 y"} {:process 44, :type :ok, :f :append, :key "6", :value "x 44 18 y"} {:process 24, :type :ok, :f :put, :key "0", :value "x 24 21 y"} {:process 40, :type :ok, :f :append, :key "1", :value "x 40 6 y"} {:process 16, :type :ok, :f :append, :key "4", :value "x 16 14 y"} {:process 3, :type :invoke, :f :append, :key "0", :value "x 3 0 y"} {:process 0, :type :invoke, :f :get, :key "7", :value nil} {:process 16, :type :invoke, :f :get, :key "6", :value nil} {:process 1, :type :invoke, :f :get, :key "4", :value nil} {:process 2, :type :invoke, :f :append, :key "6", :value "x 2 0 y"} {:process 49, :type :invoke, :f :append, :key "3", :value "x 49 0 y"} {:process 33, :type :invoke, :f :append, :key "8", :value "x 33 0 y"} {:process 32, :type :invoke, :f :append, :key "6", :value "x 32 0 y"} {:process 34, :type :invoke, :f :append, :key "4", :value "x 34 0 y"} {:process 17, :type :invoke, :f :get, :key "5", :value nil} {:process 35, :type :invoke, :f :append, :key "6", :value "x 35 0 y"} {:process 18, :type :invoke, :f :append, :key "2", :value "x 18 0 y"} {:process 36, :type :invoke, :f :get, :key "7", :value nil} {:process 19, :type :invoke, :f :append, :key "3", :value "x 19 0 y"} {:process 37, :type :invoke, :f :get, :key "7", :value nil} {:process 20, :type :invoke, :f :get, :key "8", :value nil} {:process 38, :type :invoke, :f :append, :key "2", :value "x 38 0 y"} {:process 21, :type :invoke, :f :get, :key "5", :value nil} {:process 39, :type :invoke, :f :get, :key "3", :value nil} {:process 22, :type :invoke, :f :append, :key "9", :value "x 22 0 y"} {:process 40, :type :invoke, :f :get, :key "8", :value nil} {:process 23, :type :invoke, :f :append, :key "6", :value "x 23 0 y"} {:process 41, :type :invoke, :f :get, :key "8", :value nil} {:process 24, :type :invoke, :f :put, :key "4", :value "x 24 0 y"} {:process 1, :type :ok, :f :get, :key "4", :value "x 31 14 yx 24 15 yx 36 15 yx 45 13 yx 10 23 yx 19 5 yx 25 10 y"} {:process 1, :type :invoke, :f :get, :key "0", :value nil} {:process 42, :type :invoke, :f :append, :key "2", :value "x 42 0 y"} {:process 25, :type :invoke, :f :append, :key "5", :value "x 25 0 y"} {:process 43, :type :invoke, :f :get, :key "6", :value nil} {:process 26, :type :invoke, :f :append, :key "0", :value "x 26 0 y"} {:process 44, :type :invoke, :f :get, :key "3", :value nil} {:process 27, :type :invoke, :f :get, :key "3", :value nil} {:process 45, :type :invoke, :f :append, :key "5", :value "x 45 0 y"} {:process 28, :type :invoke, :f :append, :key "6", :value "x 28 0 y"} {:process 46, :type :invoke, :f :get, :key "2", :value nil} {:process 29, :type :invoke, :f :append, :key "8", :value "x 29 0 y"} {:process 47, :type :invoke, :f :append, :key "5", :value "x 47 0 y"} {:process 30, :type :invoke, :f :append, :key "0", :value "x 30 0 y"} {:process 48, :type :invoke, :f :get, :key "9", :value nil} {:process 31, :type :invoke, :f :append, :key "7", :value "x 31 0 y"} {:process 12, :type :invoke, :f :get, :key "8", :value nil} {:process 9, :type :invoke, :f :get, :key "9", :value nil} {:process 10, :type :invoke, :f :get, :key "4", :value nil} {:process 4, :type :invoke, :f :append, :key "3", :value "x 4 0 y"} {:process 5, :type :invoke, :f :get, :key "4", :value nil} {:process 11, :type :invoke, :f :append, :key "6", :value "x 11 0 y"} {:process 6, :type :invoke, :f :append, :key "2", :value "x 6 0 y"} {:process 7, :type :invoke, :f :get, :key "7", :value nil} {:process 8, :type :invoke, :f :get, :key "6", :value nil} {:process 14, :type :invoke, :f :append, :key "5", :value "x 14 0 y"} {:process 13, :type :invoke, :f :append, :key "3", :value "x 13 0 y"} {:process 15, :type :invoke, :f :append, :key "3", :value "x 15 0 y"} {:process 16, :type :ok, :f :get, :key "6", :value "x 47 7 yx 47 8 yx 43 12 yx 6 19 yx 13 17 yx 35 5 yx 31 9 yx 44 15 yx 44 16 yx 44 18 yx 41 9 yx 33 6 y"} {:process 16, :type :invoke, :f :get, :key "3", :value nil} {:process 5, :type :ok, :f :get, :key "4", :value "x 31 14 yx 24 15 yx 36 15 yx 45 13 yx 10 23 yx 19 5 yx 25 10 yx 16 14 y"} {:process 5, :type :invoke, :f :append, :key "3", :value "x 5 0 y"} {:process 10, :type :ok, :f :get, :key "4", :value "x 31 14 yx 24 15 yx 36 15 yx 45 13 yx 10 23 yx 19 5 yx 25 10 yx 16 14 y"} {:process 10, :type :invoke, :f :append, :key "9", :value "x 10 0 y"} {:process 37, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 yx 28 23 yx 2 13 yx 24 14 yx 14 5 yx 45 10 yx 45 12 yx 37 12 yx 25 9 yx 35 8 y"} {:process 37, :type :invoke, :f :append, :key "5", :value "x 37 0 y"} {:process 40, :type :ok, :f :get, :key "8", :value "x 2 10 yx 24 13 yx 34 3 yx 47 13 y"} {:process 40, :type :invoke, :f :get, :key "1", :value nil} {:process 39, :type :ok, :f :get, :key "3", :value "x 6 21 yx 11 20 yx 26 14 y"} {:process 39, :type :invoke, :f :put, :key "7", :value "x 39 0 y"} {:process 40, :type :ok, :f :get, :key "1", :value "x 36 14 yx 8 18 yx 39 19 yx 28 24 yx 0 20 yx 22 13 yx 31 17 y"} {:process 40, :type :invoke, :f :append, :key "3", :value "x 40 0 y"} {:process 12, :type :ok, :f :get, :key "8", :value "x 2 10 yx 24 13 yx 34 3 yx 47 13 y"} {:process 12, :type :invoke, :f :append, :key "5", :value "x 12 0 y"} {:process 20, :type :ok, :f :get, :key "8", :value "x 2 10 yx 24 13 yx 34 3 yx 47 13 y"} {:process 20, :type :invoke, :f :append, :key "7", :value "x 20 0 y"} {:process 0, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 yx 28 23 yx 2 13 yx 24 14 yx 14 5 yx 45 10 yx 45 12 yx 37 12 yx 25 9 yx 35 8 y"} {:process 0, :type :invoke, :f :get, :key "1", :value nil} {:process 3, :type :ok, :f :append, :key "0", :value "x 3 0 y"} {:process 3, :type :invoke, :f :append, :key "9", :value "x 3 1 y"} {:process 43, :type :ok, :f :get, :key "6", :value "x 47 7 yx 47 8 yx 43 12 yx 6 19 yx 13 17 yx 35 5 yx 31 9 yx 44 15 yx 44 16 yx 44 18 yx 41 9 yx 33 6 y"} {:process 43, :type :invoke, :f :append, :key "7", :value "x 43 0 y"} {:process 36, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 yx 28 23 yx 2 13 yx 24 14 yx 14 5 yx 45 10 yx 45 12 yx 37 12 yx 25 9 yx 35 8 y"} {:process 36, :type :invoke, :f :append, :key "0", :value "x 36 0 y"} {:process 8, :type :ok, :f :get, :key "6", :value "x 47 7 yx 47 8 yx 43 12 yx 6 19 yx 13 17 yx 35 5 yx 31 9 yx 44 15 yx 44 16 yx 44 18 yx 41 9 yx 33 6 y"} {:process 8, :type :invoke, :f :get, :key "0", :value nil} {:process 17, :type :ok, :f :get, :key "5", :value "x 45 11 yx 29 7 y"} {:process 17, :type :invoke, :f :get, :key "5", :value nil} {:process 27, :type :ok, :f :get, :key "3", :value "x 6 21 yx 11 20 yx 26 14 y"} {:process 27, :type :invoke, :f :append, :key "4", :value "x 27 0 y"} {:process 1, :type :ok, :f :get, :key "0", :value "x 4 11 yx 3 0 y"} {:process 1, :type :invoke, :f :get, :key "1", :value nil} {:process 44, :type :ok, :f :get, :key "3", :value "x 6 21 yx 11 20 yx 26 14 y"} {:process 44, :type :invoke, :f :get, :key "8", :value nil} {:process 39, :type :ok, :f :put, :key "7", :value "x 39 0 y"} {:process 39, :type :invoke, :f :get, :key "1", :value nil} {:process 7, :type :ok, :f :get, :key "7", :value "x 25 8 yx 16 13 yx 28 20 yx 0 18 yx 28 23 yx 2 13 yx 24 14 yx 14 5 yx 45 10 yx 45 12 yx 37 12 yx 25 9 yx 35 8 y"} {:process 7, :type :invoke, :f :get, :key "5", :value nil} {:process 48, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 yx 0 16 yx 7 5 yx 15 15 yx 33 3 yx 18 13 yx 40 2 yx 43 8 yx 28 21 yx 21 9 yx 41 7 yx 42 13 yx 45 9 yx 48 7 yx 21 11 yx 35 7 yx 23 10 yx 31 12 yx 8 17 yx 31 15 yx 24 12 yx 24 16 yx 14 6 yx 9 2 yx 32 7 yx 23 11 yx 20 9 y"} {:process 48, :type :invoke, :f :append, :key "4", :value "x 48 0 y"} {:process 46, :type :ok, :f :get, :key "2", :value "x 18 16 yx 31 13 yx 2 15 yx 15 16 yx 24 17 yx 24 18 yx 44 17 yx 3 16 yx 14 7 y"} {:process 46, :type :invoke, :f :get, :key "5", :value nil} {:process 46, :type :ok, :f :get, :key "5", :value "x 45 11 yx 29 7 y"} {:process 46, :type :invoke, :f :append, :key "6", :value "x 46 0 y"} {:process 44, :type :ok, :f :get, :key "8", :value "x 2 10 yx 24 13 yx 34 3 yx 47 13 y"} {:process 44, :type :invoke, :f :append, :key "3", :value "x 44 0 y"} {:process 45, :type :ok, :f :append, :key "5", :value "x 45 0 y"} {:process 45, :type :invoke, :f :get, :key "1", :value nil} {:process 8, :type :ok, :f :get, :key "0", :value "x 4 11 yx 3 0 y"} {:process 8, :type :invoke, :f :append, :key "3", :value "x 8 0 y"} {:process 16, :type :ok, :f :get, :key "3", :value "x 6 21 yx 11 20 yx 26 14 yx 40 0 y"} {:process 16, :type :invoke, :f :get, :key "2", :value nil} {:process 1, :type :ok, :f :get, :key "1", :value "x 36 14 yx 8 18 yx 39 19 yx 28 24 yx 0 20 yx 22 13 yx 31 17 y"} {:process 1, :type :invoke, :f :get, :key "8", :value nil} {:process 45, :type :ok, :f :get, :key "1", :value "x 36 14 yx 8 18 yx 39 19 yx 28 24 yx 0 20 yx 22 13 yx 31 17 y"} {:process 45, :type :invoke, :f :get, :key "7", :value nil} {:process 1, :type :ok, :f :get, :key "8", :value "x 2 10 yx 24 13 yx 34 3 yx 47 13 y"} {:process 1, :type :invoke, :f :get, :key "7", :value nil} {:process 7, :type :ok, :f :get, :key "5", :value "x 45 11 yx 29 7 y"} {:process 7, :type :invoke, :f :append, :key "3", :value "x 7 0 y"} {:process 3, :type :ok, :f :append, :key "9", :value "x 3 1 y"} {:process 3, :type :invoke, :f :append, :key "3", :value "x 3 2 y"} {:process 5, :type :ok, :f :append, :key "3", :value "x 5 0 y"} {:process 5, :type :invoke, :f :append, :key "8", :value "x 5 1 y"} {:process 17, :type :ok, :f :get, :key "5", :value "x 45 11 yx 29 7 y"} {:process 17, :type :invoke, :f :append, :key "7", :value "x 17 0 y"} {:process 45, :type :ok, :f :get, :key "7", :value "x 39 0 y"} {:process 45, :type :invoke, :f :append, :key "7", :value "x 45 1 y"} {:process 46, :type :ok, :f :append, :key "6", :value "x 46 0 y"} {:process 46, :type :invoke, :f :put, :key "0", :value "x 46 1 y"} {:process 3, :type :ok, :f :append, :key "3", :value "x 3 2 y"} {:process 3, :type :invoke, :f :append, :key "4", :value "x 3 3 y"} {:process 1, :type :ok, :f :get, :key "7", :value "x 39 0 y"} {:process 1, :type :invoke, :f :get, :key "6", :value nil} {:process 45, :type :ok, :f :append, :key "7", :value "x 45 1 y"} {:process 45, :type :invoke, :f :append, :key "0", :value "x 45 2 y"} {:process 45, :type :ok, :f :append, :key "0", :value "x 45 2 y"} {:process 45, :type :invoke, :f :get, :key "8", :value nil} {:process 3, :type :ok, :f :append, :key "4", :value "x 3 3 y"} {:process 3, :type :invoke, :f :append, :key "6", :value "x 3 4 y"} {:process 45, :type :ok, :f :get, :key "8", :value "x 2 10 yx 24 13 yx 34 3 yx 47 13 yx 5 1 y"} {:process 45, :type :invoke, :f :append, :key "7", :value "x 45 3 y"} {:process 2, :type :ok, :f :append, :key "6", :value "x 2 0 y"} {:process 2, :type :invoke, :f :append, :key "5", :value "x 2 1 y"} {:process 3, :type :ok, :f :append, :key "6", :value "x 3 4 y"} {:process 3, :type :invoke, :f :get, :key "8", :value nil} {:process 3, :type :ok, :f :get, :key "8", :value "x 2 10 yx 24 13 yx 34 3 yx 47 13 yx 5 1 y"} {:process 3, :type :invoke, :f :append, :key "2", :value "x 3 5 y"} {:process 21, :type :ok, :f :get, :key "5", :value "x 45 11 yx 29 7 yx 45 0 yx 47 0 y"} {:process 21, :type :invoke, :f :append, :key "5", :value "x 21 0 y"} {:process 34, :type :ok, :f :append, :key "4", :value "x 34 0 y"} {:process 34, :type :invoke, :f :append, :key "9", :value "x 34 1 y"} {:process 9, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 yx 0 16 yx 7 5 yx 15 15 yx 33 3 yx 18 13 yx 40 2 yx 43 8 yx 28 21 yx 21 9 yx 41 7 yx 42 13 yx 45 9 yx 48 7 yx 21 11 yx 35 7 yx 23 10 yx 31 12 yx 8 17 yx 31 15 yx 24 12 yx 24 16 yx 14 6 yx 9 2 yx 32 7 yx 23 11 yx 20 9 yx 3 1 y"} {:process 9, :type :invoke, :f :append, :key "2", :value "x 9 0 y"} {:process 45, :type :ok, :f :append, :key "7", :value "x 45 3 y"} {:process 45, :type :invoke, :f :append, :key "7", :value "x 45 4 y"} {:process 34, :type :ok, :f :append, :key "9", :value "x 34 1 y"} {:process 4, :type :ok, :f :append, :key "3", :value "x 4 0 y"} {:process 34, :type :invoke, :f :get, :key "0", :value nil} {:process 4, :type :invoke, :f :append, :key "3", :value "x 4 1 y"} {:process 34, :type :ok, :f :get, :key "0", :value "x 46 1 yx 45 2 y"} {:process 34, :type :invoke, :f :get, :key "9", :value nil} {:process 16, :type :ok, :f :get, :key "2", :value "x 18 16 yx 31 13 yx 2 15 yx 15 16 yx 24 17 yx 24 18 yx 44 17 yx 3 16 yx 14 7 y"} {:process 16, :type :invoke, :f :put, :key "4", :value "x 16 0 y"} {:process 39, :type :ok, :f :get, :key "1", :value "x 36 14 yx 8 18 yx 39 19 yx 28 24 yx 0 20 yx 22 13 yx 31 17 y"} {:process 39, :type :invoke, :f :get, :key "6", :value nil} {:process 4, :type :ok, :f :append, :key "3", :value "x 4 1 y"} {:process 4, :type :invoke, :f :append, :key "7", :value "x 4 2 y"} {:process 39, :type :ok, :f :get, :key "6", :value "x 47 7 yx 47 8 yx 43 12 yx 6 19 yx 13 17 yx 35 5 yx 31 9 yx 44 15 yx 44 16 yx 44 18 yx 41 9 yx 33 6 yx 46 0 yx 2 0 yx 3 4 y"} {:process 39, :type :invoke, :f :get, :key "7", :value nil} {:process 4, :type :ok, :f :append, :key "7", :value "x 4 2 y"} {:process 4, :type :invoke, :f :append, :key "9", :value "x 4 3 y"} {:process 17, :type :ok, :f :append, :key "7", :value "x 17 0 y"} {:process 17, :type :invoke, :f :append, :key "5", :value "x 17 1 y"} {:process 41, :type :ok, :f :get, :key "8", :value "x 2 10 yx 24 13 yx 34 3 yx 47 13 yx 5 1 y"} {:process 41, :type :invoke, :f :append, :key "8", :value "x 41 0 y"} {:process 4, :type :ok, :f :append, :key "9", :value "x 4 3 y"} {:process 4, :type :invoke, :f :get, :key "9", :value nil} {:process 4, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 yx 0 16 yx 7 5 yx 15 15 yx 33 3 yx 18 13 yx 40 2 yx 43 8 yx 28 21 yx 21 9 yx 41 7 yx 42 13 yx 45 9 yx 48 7 yx 21 11 yx 35 7 yx 23 10 yx 31 12 yx 8 17 yx 31 15 yx 24 12 yx 24 16 yx 14 6 yx 9 2 yx 32 7 yx 23 11 yx 20 9 yx 3 1 yx 34 1 yx 4 3 y"} {:process 4, :type :invoke, :f :append, :key "7", :value "x 4 4 y"} {:process 17, :type :ok, :f :append, :key "5", :value "x 17 1 y"} {:process 17, :type :invoke, :f :append, :key "4", :value "x 17 2 y"} {:process 23, :type :ok, :f :append, :key "6", :value "x 23 0 y"} {:process 23, :type :invoke, :f :append, :key "9", :value "x 23 1 y"} {:process 4, :type :ok, :f :append, :key "7", :value "x 4 4 y"} {:process 4, :type :invoke, :f :append, :key "9", :value "x 4 5 y"} {:process 17, :type :ok, :f :append, :key "4", :value "x 17 2 y"} {:process 17, :type :invoke, :f :get, :key "4", :value nil} {:process 31, :type :ok, :f :append, :key "7", :value "x 31 0 y"} {:process 31, :type :invoke, :f :append, :key "5", :value "x 31 1 y"} {:process 18, :type :ok, :f :append, :key "2", :value "x 18 0 y"} {:process 18, :type :invoke, :f :get, :key "0", :value nil} {:process 27, :type :ok, :f :append, :key "4", :value "x 27 0 y"} {:process 27, :type :invoke, :f :append, :key "2", :value "x 27 1 y"} {:process 30, :type :ok, :f :append, :key "0", :value "x 30 0 y"} {:process 30, :type :invoke, :f :put, :key "2", :value "x 30 1 y"} {:process 4, :type :ok, :f :append, :key "9", :value "x 4 5 y"} {:process 4, :type :invoke, :f :put, :key "8", :value "x 4 6 y"} {:process 0, :type :ok, :f :get, :key "1", :value "x 36 14 yx 8 18 yx 39 19 yx 28 24 yx 0 20 yx 22 13 yx 31 17 y"} {:process 0, :type :invoke, :f :get, :key "6", :value nil} {:process 17, :type :ok, :f :get, :key "4", :value "x 31 14 yx 24 15 yx 36 15 yx 45 13 yx 10 23 yx 19 5 yx 25 10 yx 16 14 yx 3 3 yx 34 0 yx 17 2 yx 27 0 y"} {:process 17, :type :invoke, :f :get, :key "6", :value nil} {:process 18, :type :ok, :f :get, :key "0", :value "x 46 1 yx 45 2 yx 30 0 y"} {:process 18, :type :invoke, :f :get, :key "7", :value nil} {:process 17, :type :ok, :f :get, :key "6", :value "x 47 7 yx 47 8 yx 43 12 yx 6 19 yx 13 17 yx 35 5 yx 31 9 yx 44 15 yx 44 16 yx 44 18 yx 41 9 yx 33 6 yx 46 0 yx 2 0 yx 3 4 yx 23 0 y"} {:process 17, :type :invoke, :f :append, :key "5", :value "x 17 3 y"} {:process 31, :type :ok, :f :append, :key "5", :value "x 31 1 y"} {:process 31, :type :invoke, :f :append, :key "4", :value "x 31 2 y"} {:process 23, :type :ok, :f :append, :key "9", :value "x 23 1 y"} {:process 23, :type :invoke, :f :append, :key "3", :value "x 23 2 y"} {:process 17, :type :ok, :f :append, :key "5", :value "x 17 3 y"} {:process 17, :type :invoke, :f :put, :key "6", :value "x 17 4 y"} {:process 8, :type :ok, :f :append, :key "3", :value "x 8 0 y"} {:process 8, :type :invoke, :f :append, :key "2", :value "x 8 1 y"} {:process 27, :type :ok, :f :append, :key "2", :value "x 27 1 y"} {:process 27, :type :invoke, :f :append, :key "5", :value "x 27 2 y"} {:process 34, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 yx 0 16 yx 7 5 yx 15 15 yx 33 3 yx 18 13 yx 40 2 yx 43 8 yx 28 21 yx 21 9 yx 41 7 yx 42 13 yx 45 9 yx 48 7 yx 21 11 yx 35 7 yx 23 10 yx 31 12 yx 8 17 yx 31 15 yx 24 12 yx 24 16 yx 14 6 yx 9 2 yx 32 7 yx 23 11 yx 20 9 yx 3 1 yx 34 1 yx 4 3 y"} {:process 34, :type :invoke, :f :append, :key "5", :value "x 34 2 y"} {:process 17, :type :ok, :f :put, :key "6", :value "x 17 4 y"} {:process 17, :type :invoke, :f :get, :key "0", :value nil} {:process 31, :type :ok, :f :append, :key "4", :value "x 31 2 y"} {:process 31, :type :invoke, :f :append, :key "9", :value "x 31 3 y"} {:process 18, :type :ok, :f :get, :key "7", :value "x 39 0 yx 45 1 yx 45 3 yx 4 2 yx 17 0 yx 4 4 yx 31 0 y"} {:process 18, :type :invoke, :f :get, :key "7", :value nil} {:process 30, :type :ok, :f :put, :key "2", :value "x 30 1 y"} {:process 30, :type :invoke, :f :append, :key "8", :value "x 30 2 y"} {:process 27, :type :ok, :f :append, :key "5", :value "x 27 2 y"} {:process 27, :type :invoke, :f :append, :key "9", :value "x 27 3 y"} {:process 4, :type :ok, :f :put, :key "8", :value "x 4 6 y"} {:process 4, :type :invoke, :f :get, :key "6", :value nil} {:process 39, :type :ok, :f :get, :key "7", :value "x 39 0 yx 45 1 yx 45 3 yx 4 2 yx 17 0 yx 4 4 yx 31 0 y"} {:process 39, :type :invoke, :f :append, :key "7", :value "x 39 1 y"} {:process 1, :type :ok, :f :get, :key "6", :value "x 17 4 y"} {:process 1, :type :invoke, :f :get, :key "5", :value nil} {:process 23, :type :ok, :f :append, :key "3", :value "x 23 2 y"} {:process 23, :type :invoke, :f :append, :key "7", :value "x 23 3 y"} {:process 18, :type :ok, :f :get, :key "7", :value "x 39 0 yx 45 1 yx 45 3 yx 4 2 yx 17 0 yx 4 4 yx 31 0 y"} {:process 18, :type :invoke, :f :get, :key "4", :value nil} {:process 17, :type :ok, :f :get, :key "0", :value "x 46 1 yx 45 2 yx 30 0 y"} {:process 17, :type :invoke, :f :append, :key "6", :value "x 17 5 y"} {:process 8, :type :ok, :f :append, :key "2", :value "x 8 1 y"} {:process 8, :type :invoke, :f :get, :key "0", :value nil} {:process 8, :type :ok, :f :get, :key "0", :value "x 46 1 yx 45 2 yx 30 0 y"} {:process 8, :type :invoke, :f :get, :key "6", :value nil} {:process 1, :type :ok, :f :get, :key "5", :value "x 45 11 yx 29 7 yx 45 0 yx 47 0 yx 2 1 yx 17 1 yx 31 1 yx 17 3 yx 27 2 y"} {:process 1, :type :invoke, :f :append, :key "9", :value "x 1 0 y"} {:process 30, :type :ok, :f :append, :key "8", :value "x 30 2 y"} {:process 30, :type :invoke, :f :get, :key "3", :value nil} {:process 23, :type :ok, :f :append, :key "7", :value "x 23 3 y"} {:process 23, :type :invoke, :f :get, :key "4", :value nil} {:process 31, :type :ok, :f :append, :key "9", :value "x 31 3 y"} {:process 31, :type :invoke, :f :append, :key "8", :value "x 31 4 y"} {:process 30, :type :ok, :f :get, :key "3", :value "x 6 21 yx 11 20 yx 26 14 yx 40 0 yx 5 0 yx 3 2 yx 4 0 yx 4 1 yx 8 0 yx 23 2 y"} {:process 30, :type :invoke, :f :append, :key "0", :value "x 30 3 y"} {:process 18, :type :ok, :f :get, :key "4", :value "x 31 14 yx 24 15 yx 36 15 yx 45 13 yx 10 23 yx 19 5 yx 25 10 yx 16 14 yx 3 3 yx 34 0 yx 17 2 yx 27 0 yx 31 2 y"} {:process 18, :type :invoke, :f :get, :key "3", :value nil} {:process 30, :type :ok, :f :append, :key "0", :value "x 30 3 y"} {:process 30, :type :invoke, :f :get, :key "2", :value nil} {:process 17, :type :ok, :f :append, :key "6", :value "x 17 5 y"} {:process 17, :type :invoke, :f :get, :key "9", :value nil} {:process 30, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 y"} {:process 30, :type :invoke, :f :append, :key "8", :value "x 30 4 y"} {:process 17, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 yx 0 16 yx 7 5 yx 15 15 yx 33 3 yx 18 13 yx 40 2 yx 43 8 yx 28 21 yx 21 9 yx 41 7 yx 42 13 yx 45 9 yx 48 7 yx 21 11 yx 35 7 yx 23 10 yx 31 12 yx 8 17 yx 31 15 yx 24 12 yx 24 16 yx 14 6 yx 9 2 yx 32 7 yx 23 11 yx 20 9 yx 3 1 yx 34 1 yx 4 3 yx 4 5 yx 23 1 yx 31 3 y"} {:process 17, :type :invoke, :f :get, :key "0", :value nil} {:process 31, :type :ok, :f :append, :key "8", :value "x 31 4 y"} {:process 31, :type :invoke, :f :append, :key "4", :value "x 31 5 y"} {:process 18, :type :ok, :f :get, :key "3", :value "x 6 21 yx 11 20 yx 26 14 yx 40 0 yx 5 0 yx 3 2 yx 4 0 yx 4 1 yx 8 0 yx 23 2 y"} {:process 18, :type :invoke, :f :get, :key "4", :value nil} {:process 29, :type :ok, :f :append, :key "8", :value "x 29 0 y"} {:process 29, :type :invoke, :f :append, :key "4", :value "x 29 1 y"} {:process 31, :type :ok, :f :append, :key "4", :value "x 31 5 y"} {:process 31, :type :invoke, :f :append, :key "0", :value "x 31 6 y"} {:process 22, :type :ok, :f :append, :key "9", :value "x 22 0 y"} {:process 22, :type :invoke, :f :get, :key "1", :value nil} {:process 30, :type :ok, :f :append, :key "8", :value "x 30 4 y"} {:process 30, :type :invoke, :f :append, :key "2", :value "x 30 5 y"} {:process 13, :type :ok, :f :append, :key "3", :value "x 13 0 y"} {:process 13, :type :invoke, :f :get, :key "2", :value nil} {:process 30, :type :ok, :f :append, :key "2", :value "x 30 5 y"} {:process 30, :type :invoke, :f :get, :key "1", :value nil} {:process 0, :type :ok, :f :get, :key "6", :value "x 17 4 yx 17 5 y"} {:process 0, :type :invoke, :f :get, :key "5", :value nil} {:process 31, :type :ok, :f :append, :key "0", :value "x 31 6 y"} {:process 31, :type :invoke, :f :append, :key "6", :value "x 31 7 y"} {:process 9, :type :ok, :f :append, :key "2", :value "x 9 0 y"} {:process 9, :type :invoke, :f :append, :key "2", :value "x 9 1 y"} {:process 29, :type :ok, :f :append, :key "4", :value "x 29 1 y"} {:process 29, :type :invoke, :f :get, :key "5", :value nil} {:process 0, :type :ok, :f :get, :key "5", :value "x 45 11 yx 29 7 yx 45 0 yx 47 0 yx 2 1 yx 17 1 yx 31 1 yx 17 3 yx 27 2 y"} {:process 0, :type :invoke, :f :append, :key "4", :value "x 0 0 y"} {:process 30, :type :ok, :f :get, :key "1", :value "x 36 14 yx 8 18 yx 39 19 yx 28 24 yx 0 20 yx 22 13 yx 31 17 y"} {:process 30, :type :invoke, :f :get, :key "8", :value nil} {:process 9, :type :ok, :f :append, :key "2", :value "x 9 1 y"} {:process 9, :type :invoke, :f :append, :key "7", :value "x 9 2 y"} {:process 31, :type :ok, :f :append, :key "6", :value "x 31 7 y"} {:process 31, :type :invoke, :f :append, :key "2", :value "x 31 8 y"} {:process 23, :type :ok, :f :get, :key "4", :value "x 31 14 yx 24 15 yx 36 15 yx 45 13 yx 10 23 yx 19 5 yx 25 10 yx 16 14 yx 3 3 yx 34 0 yx 17 2 yx 27 0 yx 31 2 yx 31 5 y"} {:process 23, :type :invoke, :f :append, :key "1", :value "x 23 4 y"} {:process 9, :type :ok, :f :append, :key "7", :value "x 9 2 y"} {:process 9, :type :invoke, :f :get, :key "6", :value nil} {:process 4, :type :ok, :f :get, :key "6", :value "x 17 4 yx 17 5 y"} {:process 4, :type :invoke, :f :append, :key "6", :value "x 4 7 y"} {:process 8, :type :ok, :f :get, :key "6", :value "x 17 4 yx 17 5 yx 31 7 y"} {:process 8, :type :invoke, :f :append, :key "8", :value "x 8 2 y"} {:process 11, :type :ok, :f :append, :key "6", :value "x 11 0 y"} {:process 11, :type :invoke, :f :get, :key "3", :value nil} {:process 31, :type :ok, :f :append, :key "2", :value "x 31 8 y"} {:process 31, :type :invoke, :f :put, :key "0", :value "x 31 9 y"} {:process 17, :type :ok, :f :get, :key "0", :value "x 46 1 yx 45 2 yx 30 0 yx 30 3 yx 31 6 y"} {:process 17, :type :invoke, :f :append, :key "8", :value "x 17 6 y"} {:process 42, :type :ok, :f :append, :key "2", :value "x 42 0 y"} {:process 42, :type :invoke, :f :append, :key "0", :value "x 42 1 y"} {:process 28, :type :ok, :f :append, :key "6", :value "x 28 0 y"} {:process 28, :type :invoke, :f :get, :key "1", :value nil} {:process 28, :type :ok, :f :get, :key "1", :value "x 36 14 yx 8 18 yx 39 19 yx 28 24 yx 0 20 yx 22 13 yx 31 17 y"} {:process 28, :type :invoke, :f :get, :key "7", :value nil} {:process 13, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 y"} {:process 13, :type :invoke, :f :get, :key "5", :value nil} {:process 13, :type :ok, :f :get, :key "5", :value "x 45 11 yx 29 7 yx 45 0 yx 47 0 yx 2 1 yx 17 1 yx 31 1 yx 17 3 yx 27 2 y"} {:process 13, :type :invoke, :f :append, :key "6", :value "x 13 1 y"} {:process 42, :type :ok, :f :append, :key "0", :value "x 42 1 y"} {:process 42, :type :invoke, :f :get, :key "0", :value nil} {:process 29, :type :ok, :f :get, :key "5", :value "x 45 11 yx 29 7 yx 45 0 yx 47 0 yx 2 1 yx 17 1 yx 31 1 yx 17 3 yx 27 2 y"} {:process 29, :type :invoke, :f :append, :key "5", :value "x 29 2 y"} {:process 30, :type :ok, :f :get, :key "8", :value "x 4 6 yx 30 2 yx 31 4 yx 29 0 yx 30 4 y"} {:process 30, :type :invoke, :f :append, :key "5", :value "x 30 6 y"} {:process 42, :type :ok, :f :get, :key "0", :value "x 31 9 yx 42 1 y"} {:process 42, :type :invoke, :f :append, :key "3", :value "x 42 2 y"} {:process 42, :type :ok, :f :append, :key "3", :value "x 42 2 y"} {:process 42, :type :invoke, :f :append, :key "1", :value "x 42 3 y"} {:process 26, :type :ok, :f :append, :key "0", :value "x 26 0 y"} {:process 26, :type :invoke, :f :append, :key "5", :value "x 26 1 y"} {:process 18, :type :ok, :f :get, :key "4", :value "x 31 14 yx 24 15 yx 36 15 yx 45 13 yx 10 23 yx 19 5 yx 25 10 yx 16 14 yx 3 3 yx 34 0 yx 17 2 yx 27 0 yx 31 2 yx 31 5 yx 29 1 y"} {:process 18, :type :invoke, :f :get, :key "8", :value nil} {:process 42, :type :ok, :f :append, :key "1", :value "x 42 3 y"} {:process 42, :type :invoke, :f :get, :key "0", :value nil} {:process 1, :type :ok, :f :append, :key "9", :value "x 1 0 y"} {:process 1, :type :invoke, :f :get, :key "1", :value nil} {:process 26, :type :ok, :f :append, :key "5", :value "x 26 1 y"} {:process 26, :type :invoke, :f :get, :key "3", :value nil} {:process 18, :type :ok, :f :get, :key "8", :value "x 4 6 yx 30 2 yx 31 4 yx 29 0 yx 30 4 y"} {:process 18, :type :invoke, :f :get, :key "0", :value nil} {:process 22, :type :ok, :f :get, :key "1", :value "x 36 14 yx 8 18 yx 39 19 yx 28 24 yx 0 20 yx 22 13 yx 31 17 y"} {:process 22, :type :invoke, :f :get, :key "0", :value nil} {:process 42, :type :ok, :f :get, :key "0", :value "x 31 9 yx 42 1 yx 36 0 yx 26 0 y"} {:process 42, :type :invoke, :f :get, :key "6", :value nil} {:process 38, :type :ok, :f :append, :key "2", :value "x 38 0 y"} {:process 38, :type :invoke, :f :put, :key "7", :value "x 38 1 y"} {:process 26, :type :ok, :f :get, :key "3", :value "x 6 21 yx 11 20 yx 26 14 yx 40 0 yx 5 0 yx 3 2 yx 4 0 yx 4 1 yx 8 0 yx 23 2 yx 13 0 yx 15 0 yx 42 2 y"} {:process 26, :type :invoke, :f :append, :key "3", :value "x 26 2 y"} {:process 18, :type :ok, :f :get, :key "0", :value "x 31 9 yx 42 1 yx 36 0 yx 26 0 y"} {:process 18, :type :invoke, :f :append, :key "7", :value "x 18 1 y"} {:process 37, :type :ok, :f :append, :key "5", :value "x 37 0 y"} {:process 37, :type :invoke, :f :append, :key "6", :value "x 37 1 y"} {:process 22, :type :ok, :f :get, :key "0", :value "x 31 9 yx 42 1 yx 36 0 yx 26 0 y"} {:process 22, :type :invoke, :f :append, :key "1", :value "x 22 1 y"} {:process 44, :type :ok, :f :append, :key "3", :value "x 44 0 y"} {:process 44, :type :invoke, :f :get, :key "6", :value nil} {:process 26, :type :ok, :f :append, :key "3", :value "x 26 2 y"} {:process 26, :type :invoke, :f :get, :key "3", :value nil} {:process 42, :type :ok, :f :get, :key "6", :value "x 17 4 yx 17 5 yx 31 7 yx 11 0 yx 28 0 y"} {:process 42, :type :invoke, :f :put, :key "0", :value "x 42 4 y"} {:process 38, :type :ok, :f :put, :key "7", :value "x 38 1 y"} {:process 38, :type :invoke, :f :append, :key "7", :value "x 38 2 y"} {:process 26, :type :ok, :f :get, :key "3", :value "x 6 21 yx 11 20 yx 26 14 yx 40 0 yx 5 0 yx 3 2 yx 4 0 yx 4 1 yx 8 0 yx 23 2 yx 13 0 yx 15 0 yx 42 2 yx 44 0 yx 26 2 y"} {:process 26, :type :invoke, :f :append, :key "2", :value "x 26 3 y"} {:process 32, :type :ok, :f :append, :key "6", :value "x 32 0 y"} {:process 32, :type :invoke, :f :append, :key "8", :value "x 32 1 y"} {:process 9, :type :ok, :f :get, :key "6", :value "x 17 4 yx 17 5 yx 31 7 yx 11 0 yx 28 0 y"} {:process 9, :type :invoke, :f :append, :key "3", :value "x 9 3 y"} {:process 38, :type :ok, :f :append, :key "7", :value "x 38 2 y"} {:process 38, :type :invoke, :f :get, :key "3", :value nil} {:process 19, :type :ok, :f :append, :key "3", :value "x 19 0 y"} {:process 19, :type :invoke, :f :append, :key "1", :value "x 19 1 y"} {:process 38, :type :ok, :f :get, :key "3", :value "x 6 21 yx 11 20 yx 26 14 yx 40 0 yx 5 0 yx 3 2 yx 4 0 yx 4 1 yx 8 0 yx 23 2 yx 13 0 yx 15 0 yx 42 2 yx 44 0 yx 26 2 yx 19 0 y"} {:process 38, :type :invoke, :f :append, :key "4", :value "x 38 3 y"} {:process 26, :type :ok, :f :append, :key "2", :value "x 26 3 y"} {:process 26, :type :invoke, :f :get, :key "4", :value nil} {:process 19, :type :ok, :f :append, :key "1", :value "x 19 1 y"} {:process 19, :type :invoke, :f :append, :key "2", :value "x 19 2 y"} {:process 11, :type :ok, :f :get, :key "3", :value "x 6 21 yx 11 20 yx 26 14 yx 40 0 yx 5 0 yx 3 2 yx 4 0 yx 4 1 yx 8 0 yx 23 2 yx 13 0 yx 15 0 yx 42 2 yx 44 0 yx 26 2 y"} {:process 11, :type :invoke, :f :append, :key "8", :value "x 11 1 y"} {:process 14, :type :ok, :f :append, :key "5", :value "x 14 0 y"} {:process 14, :type :invoke, :f :append, :key "2", :value "x 14 1 y"} {:process 32, :type :ok, :f :append, :key "8", :value "x 32 1 y"} {:process 32, :type :invoke, :f :get, :key "0", :value nil} {:process 35, :type :ok, :f :append, :key "6", :value "x 35 0 y"} {:process 35, :type :invoke, :f :append, :key "0", :value "x 35 1 y"} {:process 49, :type :ok, :f :append, :key "3", :value "x 49 0 y"} {:process 49, :type :invoke, :f :append, :key "8", :value "x 49 1 y"} {:process 25, :type :ok, :f :append, :key "5", :value "x 25 0 y"} {:process 25, :type :invoke, :f :append, :key "4", :value "x 25 1 y"} {:process 14, :type :ok, :f :append, :key "2", :value "x 14 1 y"} {:process 14, :type :invoke, :f :append, :key "7", :value "x 14 2 y"} {:process 26, :type :ok, :f :get, :key "4", :value "x 31 14 yx 24 15 yx 36 15 yx 45 13 yx 10 23 yx 19 5 yx 25 10 yx 16 14 yx 3 3 yx 34 0 yx 17 2 yx 27 0 yx 31 2 yx 31 5 yx 29 1 yx 38 3 y"} {:process 26, :type :invoke, :f :append, :key "9", :value "x 26 4 y"} {:process 12, :type :ok, :f :append, :key "5", :value "x 12 0 y"} {:process 12, :type :invoke, :f :get, :key "1", :value nil} {:process 19, :type :ok, :f :append, :key "2", :value "x 19 2 y"} {:process 19, :type :invoke, :f :get, :key "3", :value nil} {:process 32, :type :ok, :f :get, :key "0", :value "x 31 9 yx 42 1 yx 36 0 yx 26 0 y"} {:process 32, :type :invoke, :f :append, :key "2", :value "x 32 2 y"} {:process 35, :type :ok, :f :append, :key "0", :value "x 35 1 y"} {:process 35, :type :invoke, :f :get, :key "0", :value nil} {:process 35, :type :ok, :f :get, :key "0", :value "x 31 9 yx 42 1 yx 36 0 yx 26 0 yx 35 1 y"} {:process 35, :type :invoke, :f :get, :key "2", :value nil} {:process 6, :type :ok, :f :append, :key "2", :value "x 6 0 y"} {:process 6, :type :invoke, :f :append, :key "2", :value "x 6 1 y"} {:process 19, :type :ok, :f :get, :key "3", :value "x 6 21 yx 11 20 yx 26 14 yx 40 0 yx 5 0 yx 3 2 yx 4 0 yx 4 1 yx 8 0 yx 23 2 yx 13 0 yx 15 0 yx 42 2 yx 44 0 yx 26 2 yx 19 0 yx 49 0 y"} {:process 19, :type :invoke, :f :append, :key "1", :value "x 19 3 y"} {:process 28, :type :ok, :f :get, :key "7", :value "x 38 1 yx 38 2 yx 43 0 y"} {:process 28, :type :invoke, :f :append, :key "0", :value "x 28 1 y"} {:process 49, :type :ok, :f :append, :key "8", :value "x 49 1 y"} {:process 49, :type :invoke, :f :append, :key "3", :value "x 49 2 y"} {:process 14, :type :ok, :f :append, :key "7", :value "x 14 2 y"} {:process 14, :type :invoke, :f :get, :key "3", :value nil} {:process 1, :type :ok, :f :get, :key "1", :value "x 36 14 yx 8 18 yx 39 19 yx 28 24 yx 0 20 yx 22 13 yx 31 17 yx 42 3 yx 19 1 y"} {:process 1, :type :invoke, :f :get, :key "7", :value nil} {:process 35, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 y"} {:process 35, :type :invoke, :f :append, :key "5", :value "x 35 2 y"} {:process 26, :type :ok, :f :append, :key "9", :value "x 26 4 y"} {:process 26, :type :invoke, :f :append, :key "6", :value "x 26 5 y"} {:process 25, :type :ok, :f :append, :key "4", :value "x 25 1 y"} {:process 25, :type :invoke, :f :get, :key "0", :value nil} {:process 6, :type :ok, :f :append, :key "2", :value "x 6 1 y"} {:process 6, :type :invoke, :f :append, :key "0", :value "x 6 2 y"} {:process 7, :type :ok, :f :append, :key "3", :value "x 7 0 y"} {:process 7, :type :invoke, :f :get, :key "9", :value nil} {:process 49, :type :ok, :f :append, :key "3", :value "x 49 2 y"} {:process 49, :type :invoke, :f :append, :key "2", :value "x 49 3 y"} {:process 32, :type :ok, :f :append, :key "2", :value "x 32 2 y"} {:process 32, :type :invoke, :f :get, :key "4", :value nil} {:process 32, :type :ok, :f :get, :key "4", :value "x 31 14 yx 24 15 yx 36 15 yx 45 13 yx 10 23 yx 19 5 yx 25 10 yx 16 14 yx 3 3 yx 34 0 yx 17 2 yx 27 0 yx 31 2 yx 31 5 yx 29 1 yx 38 3 yx 25 1 y"} {:process 32, :type :invoke, :f :append, :key "2", :value "x 32 3 y"} {:process 7, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 yx 0 16 yx 7 5 yx 15 15 yx 33 3 yx 18 13 yx 40 2 yx 43 8 yx 28 21 yx 21 9 yx 41 7 yx 42 13 yx 45 9 yx 48 7 yx 21 11 yx 35 7 yx 23 10 yx 31 12 yx 8 17 yx 31 15 yx 24 12 yx 24 16 yx 14 6 yx 9 2 yx 32 7 yx 23 11 yx 20 9 yx 3 1 yx 34 1 yx 4 3 yx 4 5 yx 23 1 yx 31 3 yx 22 0 yx 1 0 yx 26 4 y"} {:process 7, :type :invoke, :f :get, :key "0", :value nil} {:process 26, :type :ok, :f :append, :key "6", :value "x 26 5 y"} {:process 26, :type :invoke, :f :get, :key "5", :value nil} {:process 44, :type :ok, :f :get, :key "6", :value "x 17 4 yx 17 5 yx 31 7 yx 11 0 yx 28 0 yx 32 0 yx 35 0 y"} {:process 44, :type :invoke, :f :append, :key "6", :value "x 44 1 y"} {:process 1, :type :ok, :f :get, :key "7", :value "x 38 1 yx 38 2 yx 43 0 yx 14 2 y"} {:process 1, :type :invoke, :f :append, :key "0", :value "x 1 1 y"} {:process 25, :type :ok, :f :get, :key "0", :value "x 31 9 yx 42 1 yx 36 0 yx 26 0 yx 35 1 y"} {:process 25, :type :invoke, :f :append, :key "9", :value "x 25 2 y"} {:process 35, :type :ok, :f :append, :key "5", :value "x 35 2 y"} {:process 35, :type :invoke, :f :append, :key "4", :value "x 35 3 y"} {:process 26, :type :ok, :f :get, :key "5", :value "x 45 11 yx 29 7 yx 45 0 yx 47 0 yx 2 1 yx 17 1 yx 31 1 yx 17 3 yx 27 2 yx 26 1 yx 37 0 yx 14 0 yx 25 0 yx 12 0 yx 35 2 y"} {:process 26, :type :invoke, :f :append, :key "5", :value "x 26 6 y"} {:process 25, :type :ok, :f :append, :key "9", :value "x 25 2 y"} {:process 25, :type :invoke, :f :append, :key "0", :value "x 25 3 y"} {:process 35, :type :ok, :f :append, :key "4", :value "x 35 3 y"} {:process 35, :type :invoke, :f :get, :key "7", :value nil} {:process 35, :type :ok, :f :get, :key "7", :value "x 38 1 yx 38 2 yx 43 0 yx 14 2 y"} {:process 35, :type :invoke, :f :append, :key "4", :value "x 35 4 y"} {:process 26, :type :ok, :f :append, :key "5", :value "x 26 6 y"} {:process 26, :type :invoke, :f :get, :key "9", :value nil} {:process 25, :type :ok, :f :append, :key "0", :value "x 25 3 y"} {:process 25, :type :invoke, :f :append, :key "8", :value "x 25 4 y"} {:process 35, :type :ok, :f :append, :key "4", :value "x 35 4 y"} {:process 35, :type :invoke, :f :get, :key "5", :value nil} {:process 35, :type :ok, :f :get, :key "5", :value "x 45 11 yx 29 7 yx 45 0 yx 47 0 yx 2 1 yx 17 1 yx 31 1 yx 17 3 yx 27 2 yx 26 1 yx 37 0 yx 14 0 yx 25 0 yx 12 0 yx 35 2 yx 26 6 y"} {:process 35, :type :invoke, :f :append, :key "6", :value "x 35 5 y"} {:process 25, :type :ok, :f :append, :key "8", :value "x 25 4 y"} {:process 25, :type :invoke, :f :append, :key "3", :value "x 25 5 y"} {:process 10, :type :ok, :f :append, :key "9", :value "x 10 0 y"} {:process 10, :type :invoke, :f :append, :key "6", :value "x 10 1 y"} {:process 12, :type :ok, :f :get, :key "1", :value "x 36 14 yx 8 18 yx 39 19 yx 28 24 yx 0 20 yx 22 13 yx 31 17 yx 42 3 yx 19 1 yx 19 3 y"} {:process 12, :type :invoke, :f :append, :key "9", :value "x 12 1 y"} {:process 14, :type :ok, :f :get, :key "3", :value "x 6 21 yx 11 20 yx 26 14 yx 40 0 yx 5 0 yx 3 2 yx 4 0 yx 4 1 yx 8 0 yx 23 2 yx 13 0 yx 15 0 yx 42 2 yx 44 0 yx 26 2 yx 19 0 yx 49 0 yx 7 0 yx 49 2 y"} {:process 14, :type :invoke, :f :get, :key "1", :value nil} {:process 25, :type :ok, :f :append, :key "3", :value "x 25 5 y"} {:process 25, :type :invoke, :f :get, :key "4", :value nil} {:process 10, :type :ok, :f :append, :key "6", :value "x 10 1 y"} {:process 10, :type :invoke, :f :get, :key "7", :value nil} {:process 35, :type :ok, :f :append, :key "6", :value "x 35 5 y"} {:process 35, :type :invoke, :f :get, :key "7", :value nil} {:process 25, :type :ok, :f :get, :key "4", :value "x 31 14 yx 24 15 yx 36 15 yx 45 13 yx 10 23 yx 19 5 yx 25 10 yx 16 14 yx 3 3 yx 34 0 yx 17 2 yx 27 0 yx 31 2 yx 31 5 yx 29 1 yx 38 3 yx 25 1 yx 35 3 yx 35 4 y"} {:process 25, :type :invoke, :f :get, :key "0", :value nil} {:process 25, :type :ok, :f :get, :key "0", :value "x 31 9 yx 42 1 yx 36 0 yx 26 0 yx 35 1 yx 25 3 y"} {:process 25, :type :invoke, :f :get, :key "0", :value nil} {:process 35, :type :ok, :f :get, :key "7", :value "x 38 1 yx 38 2 yx 43 0 yx 14 2 y"} {:process 35, :type :invoke, :f :put, :key "5", :value "x 35 6 y"} {:process 25, :type :ok, :f :get, :key "0", :value "x 31 9 yx 42 1 yx 36 0 yx 26 0 yx 35 1 yx 25 3 y"} {:process 25, :type :invoke, :f :get, :key "4", :value nil} {:process 25, :type :ok, :f :get, :key "4", :value "x 31 14 yx 24 15 yx 36 15 yx 45 13 yx 10 23 yx 19 5 yx 25 10 yx 16 14 yx 3 3 yx 34 0 yx 17 2 yx 27 0 yx 31 2 yx 31 5 yx 29 1 yx 38 3 yx 25 1 yx 35 3 yx 35 4 y"} {:process 25, :type :invoke, :f :append, :key "0", :value "x 25 6 y"} {:process 35, :type :ok, :f :put, :key "5", :value "x 35 6 y"} {:process 35, :type :invoke, :f :get, :key "8", :value nil} {:process 35, :type :ok, :f :get, :key "8", :value "x 4 6 yx 30 2 yx 31 4 yx 29 0 yx 30 4 yx 32 1 yx 49 1 yx 25 4 y"} {:process 35, :type :invoke, :f :get, :key "8", :value nil} {:process 26, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 yx 0 16 yx 7 5 yx 15 15 yx 33 3 yx 18 13 yx 40 2 yx 43 8 yx 28 21 yx 21 9 yx 41 7 yx 42 13 yx 45 9 yx 48 7 yx 21 11 yx 35 7 yx 23 10 yx 31 12 yx 8 17 yx 31 15 yx 24 12 yx 24 16 yx 14 6 yx 9 2 yx 32 7 yx 23 11 yx 20 9 yx 3 1 yx 34 1 yx 4 3 yx 4 5 yx 23 1 yx 31 3 yx 22 0 yx 1 0 yx 26 4 yx 25 2 yx 10 0 y"} {:process 26, :type :invoke, :f :append, :key "0", :value "x 26 7 y"} {:process 24, :type :ok, :f :put, :key "4", :value "x 24 0 y"} {:process 24, :type :invoke, :f :get, :key "0", :value nil} {:process 35, :type :ok, :f :get, :key "8", :value "x 4 6 yx 30 2 yx 31 4 yx 29 0 yx 30 4 yx 32 1 yx 49 1 yx 25 4 y"} {:process 35, :type :invoke, :f :get, :key "5", :value nil} {:process 25, :type :ok, :f :append, :key "0", :value "x 25 6 y"} {:process 25, :type :invoke, :f :get, :key "7", :value nil} {:process 35, :type :ok, :f :get, :key "5", :value "x 35 6 y"} {:process 35, :type :invoke, :f :get, :key "7", :value nil} {:process 35, :type :ok, :f :get, :key "7", :value "x 38 1 yx 38 2 yx 43 0 yx 14 2 y"} {:process 35, :type :invoke, :f :get, :key "8", :value nil} {:process 25, :type :ok, :f :get, :key "7", :value "x 38 1 yx 38 2 yx 43 0 yx 14 2 y"} {:process 25, :type :invoke, :f :append, :key "4", :value "x 25 7 y"} {:process 10, :type :ok, :f :get, :key "7", :value "x 38 1 yx 38 2 yx 43 0 yx 14 2 y"} {:process 10, :type :invoke, :f :get, :key "6", :value nil} {:process 14, :type :ok, :f :get, :key "1", :value "x 36 14 yx 8 18 yx 39 19 yx 28 24 yx 0 20 yx 22 13 yx 31 17 yx 42 3 yx 19 1 yx 19 3 y"} {:process 14, :type :invoke, :f :append, :key "4", :value "x 14 3 y"} {:process 35, :type :ok, :f :get, :key "8", :value "x 4 6 yx 30 2 yx 31 4 yx 29 0 yx 30 4 yx 32 1 yx 49 1 yx 25 4 y"} {:process 35, :type :invoke, :f :get, :key "4", :value nil} {:process 10, :type :ok, :f :get, :key "6", :value "x 17 4 yx 17 5 yx 31 7 yx 11 0 yx 28 0 yx 32 0 yx 35 0 yx 26 5 yx 10 1 yx 35 5 y"} {:process 10, :type :invoke, :f :get, :key "0", :value nil} {:process 7, :type :ok, :f :get, :key "0", :value "x 31 9 yx 42 1 yx 36 0 yx 26 0 yx 35 1 yx 25 3 yx 25 6 y"} {:process 7, :type :invoke, :f :append, :key "6", :value "x 7 1 y"} {:process 25, :type :ok, :f :append, :key "4", :value "x 25 7 y"} {:process 25, :type :invoke, :f :append, :key "3", :value "x 25 8 y"} {:process 10, :type :ok, :f :get, :key "0", :value "x 31 9 yx 42 1 yx 36 0 yx 26 0 yx 35 1 yx 25 3 yx 25 6 y"} {:process 10, :type :invoke, :f :get, :key "3", :value nil} {:process 35, :type :ok, :f :get, :key "4", :value "x 24 0 yx 25 7 y"} {:process 35, :type :invoke, :f :append, :key "6", :value "x 35 7 y"} {:process 24, :type :ok, :f :get, :key "0", :value "x 31 9 yx 42 1 yx 36 0 yx 26 0 yx 35 1 yx 25 3 yx 25 6 y"} {:process 24, :type :invoke, :f :append, :key "9", :value "x 24 1 y"} {:process 10, :type :ok, :f :get, :key "3", :value "x 6 21 yx 11 20 yx 26 14 yx 40 0 yx 5 0 yx 3 2 yx 4 0 yx 4 1 yx 8 0 yx 23 2 yx 13 0 yx 15 0 yx 42 2 yx 44 0 yx 26 2 yx 19 0 yx 49 0 yx 7 0 yx 49 2 yx 25 5 y"} {:process 10, :type :invoke, :f :append, :key "1", :value "x 10 2 y"} {:process 32, :type :ok, :f :append, :key "2", :value "x 32 3 y"} {:process 32, :type :invoke, :f :get, :key "2", :value nil} {:process 32, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 y"} {:process 32, :type :invoke, :f :append, :key "5", :value "x 32 4 y"} {:process 7, :type :ok, :f :append, :key "6", :value "x 7 1 y"} {:process 7, :type :invoke, :f :append, :key "3", :value "x 7 2 y"} {:process 7, :type :ok, :f :append, :key "3", :value "x 7 2 y"} {:process 7, :type :invoke, :f :get, :key "6", :value nil} {:process 7, :type :ok, :f :get, :key "6", :value "x 17 4 yx 17 5 yx 31 7 yx 11 0 yx 28 0 yx 32 0 yx 35 0 yx 26 5 yx 10 1 yx 35 5 yx 7 1 yx 44 1 y"} {:process 7, :type :invoke, :f :get, :key "0", :value nil} {:process 7, :type :ok, :f :get, :key "0", :value "x 31 9 yx 42 1 yx 36 0 yx 26 0 yx 35 1 yx 25 3 yx 25 6 y"} {:process 7, :type :invoke, :f :append, :key "4", :value "x 7 3 y"} {:process 6, :type :ok, :f :append, :key "0", :value "x 6 2 y"} {:process 6, :type :invoke, :f :append, :key "5", :value "x 6 3 y"} {:process 6, :type :ok, :f :append, :key "5", :value "x 6 3 y"} {:process 6, :type :invoke, :f :append, :key "7", :value "x 6 4 y"} {:process 6, :type :ok, :f :append, :key "7", :value "x 6 4 y"} {:process 6, :type :invoke, :f :get, :key "9", :value nil} {:process 42, :type :ok, :f :put, :key "0", :value "x 42 4 y"} {:process 42, :type :invoke, :f :put, :key "6", :value "x 42 5 y"} {:process 14, :type :ok, :f :append, :key "4", :value "x 14 3 y"} {:process 14, :type :invoke, :f :append, :key "5", :value "x 14 4 y"} {:process 14, :type :ok, :f :append, :key "5", :value "x 14 4 y"} {:process 14, :type :invoke, :f :get, :key "6", :value nil} {:process 14, :type :ok, :f :get, :key "6", :value "x 42 5 y"} {:process 14, :type :invoke, :f :get, :key "1", :value nil} {:process 49, :type :ok, :f :append, :key "2", :value "x 49 3 y"} {:process 49, :type :invoke, :f :append, :key "4", :value "x 49 4 y"} {:process 8, :type :ok, :f :append, :key "8", :value "x 8 2 y"} {:process 8, :type :invoke, :f :append, :key "8", :value "x 8 3 y"} {:process 6, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 yx 0 16 yx 7 5 yx 15 15 yx 33 3 yx 18 13 yx 40 2 yx 43 8 yx 28 21 yx 21 9 yx 41 7 yx 42 13 yx 45 9 yx 48 7 yx 21 11 yx 35 7 yx 23 10 yx 31 12 yx 8 17 yx 31 15 yx 24 12 yx 24 16 yx 14 6 yx 9 2 yx 32 7 yx 23 11 yx 20 9 yx 3 1 yx 34 1 yx 4 3 yx 4 5 yx 23 1 yx 31 3 yx 22 0 yx 1 0 yx 26 4 yx 25 2 yx 10 0 y"} {:process 6, :type :invoke, :f :get, :key "4", :value nil} {:process 49, :type :ok, :f :append, :key "4", :value "x 49 4 y"} {:process 49, :type :invoke, :f :get, :key "9", :value nil} {:process 6, :type :ok, :f :get, :key "4", :value "x 24 0 yx 25 7 yx 7 3 yx 14 3 yx 49 4 y"} {:process 6, :type :invoke, :f :append, :key "9", :value "x 6 5 y"} {:process 20, :type :ok, :f :append, :key "7", :value "x 20 0 y"} {:process 20, :type :invoke, :f :get, :key "9", :value nil} {:process 20, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 yx 0 16 yx 7 5 yx 15 15 yx 33 3 yx 18 13 yx 40 2 yx 43 8 yx 28 21 yx 21 9 yx 41 7 yx 42 13 yx 45 9 yx 48 7 yx 21 11 yx 35 7 yx 23 10 yx 31 12 yx 8 17 yx 31 15 yx 24 12 yx 24 16 yx 14 6 yx 9 2 yx 32 7 yx 23 11 yx 20 9 yx 3 1 yx 34 1 yx 4 3 yx 4 5 yx 23 1 yx 31 3 yx 22 0 yx 1 0 yx 26 4 yx 25 2 yx 10 0 y"} {:process 20, :type :invoke, :f :append, :key "9", :value "x 20 1 y"} {:process 14, :type :ok, :f :get, :key "1", :value "x 36 14 yx 8 18 yx 39 19 yx 28 24 yx 0 20 yx 22 13 yx 31 17 yx 42 3 yx 19 1 yx 19 3 yx 22 1 y"} {:process 14, :type :invoke, :f :get, :key "3", :value nil} {:process 20, :type :ok, :f :append, :key "9", :value "x 20 1 y"} {:process 20, :type :invoke, :f :get, :key "6", :value nil} {:process 20, :type :ok, :f :get, :key "6", :value "x 42 5 y"} {:process 20, :type :invoke, :f :append, :key "8", :value "x 20 2 y"} {:process 14, :type :ok, :f :get, :key "3", :value "x 6 21 yx 11 20 yx 26 14 yx 40 0 yx 5 0 yx 3 2 yx 4 0 yx 4 1 yx 8 0 yx 23 2 yx 13 0 yx 15 0 yx 42 2 yx 44 0 yx 26 2 yx 19 0 yx 49 0 yx 7 0 yx 49 2 yx 25 5 yx 7 2 y"} {:process 14, :type :invoke, :f :append, :key "0", :value "x 14 5 y"} {:process 26, :type :ok, :f :append, :key "0", :value "x 26 7 y"} {:process 26, :type :invoke, :f :get, :key "5", :value nil} {:process 45, :type :ok, :f :append, :key "7", :value "x 45 4 y"} {:process 45, :type :invoke, :f :put, :key "3", :value "x 45 5 y"} {:process 49, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 yx 0 16 yx 7 5 yx 15 15 yx 33 3 yx 18 13 yx 40 2 yx 43 8 yx 28 21 yx 21 9 yx 41 7 yx 42 13 yx 45 9 yx 48 7 yx 21 11 yx 35 7 yx 23 10 yx 31 12 yx 8 17 yx 31 15 yx 24 12 yx 24 16 yx 14 6 yx 9 2 yx 32 7 yx 23 11 yx 20 9 yx 3 1 yx 34 1 yx 4 3 yx 4 5 yx 23 1 yx 31 3 yx 22 0 yx 1 0 yx 26 4 yx 25 2 yx 10 0 y"} {:process 49, :type :invoke, :f :get, :key "2", :value nil} {:process 20, :type :ok, :f :append, :key "8", :value "x 20 2 y"} {:process 20, :type :invoke, :f :append, :key "4", :value "x 20 3 y"} {:process 47, :type :ok, :f :append, :key "5", :value "x 47 0 y"} {:process 47, :type :invoke, :f :append, :key "1", :value "x 47 1 y"} {:process 26, :type :ok, :f :get, :key "5", :value "x 35 6 yx 6 3 yx 14 4 y"} {:process 26, :type :invoke, :f :get, :key "4", :value nil} {:process 10, :type :ok, :f :append, :key "1", :value "x 10 2 y"} {:process 10, :type :invoke, :f :put, :key "0", :value "x 10 3 y"} {:process 49, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 y"} {:process 49, :type :invoke, :f :get, :key "3", :value nil} {:process 40, :type :ok, :f :append, :key "3", :value "x 40 0 y"} {:process 40, :type :invoke, :f :get, :key "2", :value nil} {:process 49, :type :ok, :f :get, :key "3", :value "x 6 21 yx 11 20 yx 26 14 yx 40 0 yx 5 0 yx 3 2 yx 4 0 yx 4 1 yx 8 0 yx 23 2 yx 13 0 yx 15 0 yx 42 2 yx 44 0 yx 26 2 yx 19 0 yx 49 0 yx 7 0 yx 49 2 yx 25 5 y"} {:process 49, :type :invoke, :f :append, :key "0", :value "x 49 5 y"} {:process 45, :type :ok, :f :put, :key "3", :value "x 45 5 y"} {:process 45, :type :invoke, :f :append, :key "3", :value "x 45 6 y"} {:process 10, :type :ok, :f :put, :key "0", :value "x 10 3 y"} {:process 10, :type :invoke, :f :get, :key "2", :value nil} {:process 47, :type :ok, :f :append, :key "1", :value "x 47 1 y"} {:process 47, :type :invoke, :f :put, :key "1", :value "x 47 2 y"} {:process 26, :type :ok, :f :get, :key "4", :value "x 24 0 yx 25 7 yx 7 3 yx 14 3 yx 49 4 y"} {:process 26, :type :invoke, :f :append, :key "6", :value "x 26 8 y"} {:process 10, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 y"} {:process 10, :type :invoke, :f :get, :key "8", :value nil} {:process 40, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 y"} {:process 40, :type :invoke, :f :append, :key "2", :value "x 40 1 y"} {:process 43, :type :ok, :f :append, :key "7", :value "x 43 0 y"} {:process 43, :type :invoke, :f :get, :key "7", :value nil} {:process 45, :type :ok, :f :append, :key "3", :value "x 45 6 y"} {:process 45, :type :invoke, :f :append, :key "0", :value "x 45 7 y"} {:process 43, :type :ok, :f :get, :key "7", :value "x 38 1 yx 38 2 yx 43 0 yx 14 2 yx 6 4 yx 20 0 yx 45 4 y"} {:process 43, :type :invoke, :f :append, :key "3", :value "x 43 1 y"} {:process 47, :type :ok, :f :put, :key "1", :value "x 47 2 y"} {:process 47, :type :invoke, :f :get, :key "0", :value nil} {:process 47, :type :ok, :f :get, :key "0", :value "x 10 3 y"} {:process 47, :type :invoke, :f :append, :key "8", :value "x 47 3 y"} {:process 26, :type :ok, :f :append, :key "6", :value "x 26 8 y"} {:process 26, :type :invoke, :f :append, :key "7", :value "x 26 9 y"} {:process 45, :type :ok, :f :append, :key "0", :value "x 45 7 y"} {:process 45, :type :invoke, :f :append, :key "9", :value "x 45 8 y"} {:process 47, :type :ok, :f :append, :key "8", :value "x 47 3 y"} {:process 47, :type :invoke, :f :get, :key "0", :value nil} {:process 43, :type :ok, :f :append, :key "3", :value "x 43 1 y"} {:process 43, :type :invoke, :f :append, :key "1", :value "x 43 2 y"} {:process 26, :type :ok, :f :append, :key "7", :value "x 26 9 y"} {:process 26, :type :invoke, :f :append, :key "9", :value "x 26 10 y"} {:process 47, :type :ok, :f :get, :key "0", :value "x 10 3 yx 45 7 y"} {:process 47, :type :invoke, :f :get, :key "7", :value nil} {:process 45, :type :ok, :f :append, :key "9", :value "x 45 8 y"} {:process 45, :type :invoke, :f :get, :key "1", :value nil} {:process 47, :type :ok, :f :get, :key "7", :value "x 38 1 yx 38 2 yx 43 0 yx 14 2 yx 6 4 yx 20 0 yx 45 4 yx 26 9 y"} {:process 47, :type :invoke, :f :append, :key "4", :value "x 47 4 y"} {:process 43, :type :ok, :f :append, :key "1", :value "x 43 2 y"} {:process 43, :type :invoke, :f :get, :key "7", :value nil} {:process 43, :type :ok, :f :get, :key "7", :value "x 38 1 yx 38 2 yx 43 0 yx 14 2 yx 6 4 yx 20 0 yx 45 4 yx 26 9 y"} {:process 43, :type :invoke, :f :append, :key "8", :value "x 43 3 y"} {:process 26, :type :ok, :f :append, :key "9", :value "x 26 10 y"} {:process 26, :type :invoke, :f :append, :key "6", :value "x 26 11 y"} {:process 43, :type :ok, :f :append, :key "8", :value "x 43 3 y"} {:process 43, :type :invoke, :f :get, :key "3", :value nil} {:process 43, :type :ok, :f :get, :key "3", :value "x 45 5 yx 45 6 yx 43 1 y"} {:process 43, :type :invoke, :f :put, :key "5", :value "x 43 4 y"} {:process 47, :type :ok, :f :append, :key "4", :value "x 47 4 y"} {:process 47, :type :invoke, :f :append, :key "5", :value "x 47 5 y"} {:process 10, :type :ok, :f :get, :key "8", :value "x 4 6 yx 30 2 yx 31 4 yx 29 0 yx 30 4 yx 32 1 yx 49 1 yx 25 4 y"} {:process 10, :type :invoke, :f :append, :key "8", :value "x 10 4 y"} {:process 26, :type :ok, :f :append, :key "6", :value "x 26 11 y"} {:process 26, :type :invoke, :f :append, :key "1", :value "x 26 12 y"} {:process 43, :type :ok, :f :put, :key "5", :value "x 43 4 y"} {:process 43, :type :invoke, :f :get, :key "8", :value nil} {:process 21, :type :ok, :f :append, :key "5", :value "x 21 0 y"} {:process 21, :type :invoke, :f :append, :key "4", :value "x 21 1 y"} {:process 25, :type :ok, :f :append, :key "3", :value "x 25 8 y"} {:process 25, :type :invoke, :f :append, :key "5", :value "x 25 9 y"} {:process 47, :type :ok, :f :append, :key "5", :value "x 47 5 y"} {:process 47, :type :invoke, :f :get, :key "4", :value nil} {:process 43, :type :ok, :f :get, :key "8", :value "x 4 6 yx 30 2 yx 31 4 yx 29 0 yx 30 4 yx 32 1 yx 49 1 yx 25 4 yx 8 2 yx 20 2 yx 47 3 yx 43 3 y"} {:process 43, :type :invoke, :f :get, :key "5", :value nil} {:process 26, :type :ok, :f :append, :key "1", :value "x 26 12 y"} {:process 26, :type :invoke, :f :append, :key "5", :value "x 26 13 y"} {:process 47, :type :ok, :f :get, :key "4", :value "x 24 0 yx 25 7 yx 7 3 yx 14 3 yx 49 4 yx 47 4 y"} {:process 47, :type :invoke, :f :put, :key "9", :value "x 47 6 y"} {:process 21, :type :ok, :f :append, :key "4", :value "x 21 1 y"} {:process 21, :type :invoke, :f :get, :key "8", :value nil} {:process 26, :type :ok, :f :append, :key "5", :value "x 26 13 y"} {:process 26, :type :invoke, :f :get, :key "9", :value nil} {:process 26, :type :ok, :f :get, :key "9", :value "x 10 15 yx 8 12 yx 49 19 yx 49 20 yx 28 8 yx 3 12 yx 28 10 yx 36 5 yx 36 6 yx 45 4 yx 22 9 yx 13 12 yx 0 16 yx 7 5 yx 15 15 yx 33 3 yx 18 13 yx 40 2 yx 43 8 yx 28 21 yx 21 9 yx 41 7 yx 42 13 yx 45 9 yx 48 7 yx 21 11 yx 35 7 yx 23 10 yx 31 12 yx 8 17 yx 31 15 yx 24 12 yx 24 16 yx 14 6 yx 9 2 yx 32 7 yx 23 11 yx 20 9 yx 3 1 yx 34 1 yx 4 3 yx 4 5 yx 23 1 yx 31 3 yx 22 0 yx 1 0 yx 26 4 yx 25 2 yx 10 0 yx 20 1 yx 45 8 yx 26 10 y"} {:process 26, :type :invoke, :f :append, :key "8", :value "x 26 14 y"} {:process 21, :type :ok, :f :get, :key "8", :value "x 4 6 yx 30 2 yx 31 4 yx 29 0 yx 30 4 yx 32 1 yx 49 1 yx 25 4 yx 8 2 yx 20 2 yx 47 3 yx 43 3 y"} {:process 21, :type :invoke, :f :append, :key "3", :value "x 21 2 y"} {:process 47, :type :ok, :f :put, :key "9", :value "x 47 6 y"} {:process 47, :type :invoke, :f :append, :key "1", :value "x 47 7 y"} {:process 21, :type :ok, :f :append, :key "3", :value "x 21 2 y"} {:process 21, :type :invoke, :f :append, :key "0", :value "x 21 3 y"} {:process 26, :type :ok, :f :append, :key "8", :value "x 26 14 y"} {:process 26, :type :invoke, :f :append, :key "4", :value "x 26 15 y"} {:process 47, :type :ok, :f :append, :key "1", :value "x 47 7 y"} {:process 47, :type :invoke, :f :get, :key "1", :value nil} {:process 26, :type :ok, :f :append, :key "4", :value "x 26 15 y"} {:process 26, :type :invoke, :f :append, :key "6", :value "x 26 16 y"} {:process 43, :type :ok, :f :get, :key "5", :value "x 35 6 y"} {:process 43, :type :invoke, :f :append, :key "2", :value "x 43 5 y"} {:process 26, :type :ok, :f :append, :key "6", :value "x 26 16 y"} {:process 26, :type :invoke, :f :append, :key "2", :value "x 26 17 y"} {:process 39, :type :ok, :f :append, :key "7", :value "x 39 1 y"} {:process 39, :type :invoke, :f :get, :key "3", :value nil} {:process 47, :type :ok, :f :get, :key "1", :value "x 47 2 yx 43 2 yx 26 12 yx 47 7 y"} {:process 47, :type :invoke, :f :get, :key "1", :value nil} {:process 39, :type :ok, :f :get, :key "3", :value "x 45 5 yx 45 6 yx 43 1 yx 25 8 yx 21 2 y"} {:process 39, :type :invoke, :f :append, :key "7", :value "x 39 2 y"} {:process 47, :type :ok, :f :get, :key "1", :value "x 47 2 yx 43 2 yx 26 12 yx 47 7 y"} {:process 47, :type :invoke, :f :get, :key "0", :value nil} {:process 47, :type :ok, :f :get, :key "0", :value "x 10 3 yx 45 7 y"} {:process 47, :type :invoke, :f :get, :key "9", :value nil} {:process 47, :type :ok, :f :get, :key "9", :value "x 47 6 y"} {:process 47, :type :invoke, :f :append, :key "6", :value "x 47 8 y"} {:process 45, :type :ok, :f :get, :key "1", :value "x 47 2 yx 43 2 yx 26 12 yx 47 7 y"} {:process 45, :type :invoke, :f :append, :key "7", :value "x 45 9 y"} {:process 22, :type :ok, :f :append, :key "1", :value "x 22 1 y"} {:process 22, :type :invoke, :f :append, :key "7", :value "x 22 2 y"} {:process 44, :type :ok, :f :append, :key "6", :value "x 44 1 y"} {:process 44, :type :invoke, :f :append, :key "5", :value "x 44 2 y"} {:process 22, :type :ok, :f :append, :key "7", :value "x 22 2 y"} {:process 22, :type :invoke, :f :get, :key "9", :value nil} {:process 22, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 y"} {:process 22, :type :invoke, :f :get, :key "6", :value nil} {:process 36, :type :ok, :f :append, :key "0", :value "x 36 0 y"} {:process 36, :type :invoke, :f :append, :key "1", :value "x 36 1 y"} {:process 36, :type :ok, :f :append, :key "1", :value "x 36 1 y"} {:process 36, :type :invoke, :f :get, :key "0", :value nil} {:process 44, :type :ok, :f :append, :key "5", :value "x 44 2 y"} {:process 44, :type :invoke, :f :append, :key "9", :value "x 44 3 y"} {:process 36, :type :ok, :f :get, :key "0", :value "x 10 3 yx 45 7 y"} {:process 36, :type :invoke, :f :append, :key "6", :value "x 36 2 y"} {:process 44, :type :ok, :f :append, :key "9", :value "x 44 3 y"} {:process 44, :type :invoke, :f :get, :key "1", :value nil} {:process 36, :type :ok, :f :append, :key "6", :value "x 36 2 y"} {:process 36, :type :invoke, :f :get, :key "6", :value nil} {:process 36, :type :ok, :f :get, :key "6", :value "x 42 5 yx 26 8 yx 26 11 yx 26 16 yx 36 2 y"} {:process 36, :type :invoke, :f :append, :key "6", :value "x 36 3 y"} {:process 22, :type :ok, :f :get, :key "6", :value "x 42 5 yx 26 8 yx 26 11 yx 26 16 y"} {:process 22, :type :invoke, :f :append, :key "4", :value "x 22 3 y"} {:process 47, :type :ok, :f :append, :key "6", :value "x 47 8 y"} {:process 47, :type :invoke, :f :append, :key "2", :value "x 47 9 y"} {:process 36, :type :ok, :f :append, :key "6", :value "x 36 3 y"} {:process 36, :type :invoke, :f :get, :key "5", :value nil} {:process 36, :type :ok, :f :get, :key "5", :value "x 43 4 yx 21 0 yx 47 5 yx 26 13 yx 44 2 y"} {:process 36, :type :invoke, :f :get, :key "3", :value nil} {:process 36, :type :ok, :f :get, :key "3", :value "x 45 5 yx 45 6 yx 43 1 yx 25 8 yx 21 2 y"} {:process 36, :type :invoke, :f :get, :key "0", :value nil} {:process 32, :type :ok, :f :append, :key "5", :value "x 32 4 y"} {:process 32, :type :invoke, :f :get, :key "2", :value nil} {:process 47, :type :ok, :f :append, :key "2", :value "x 47 9 y"} {:process 47, :type :invoke, :f :append, :key "3", :value "x 47 10 y"} {:process 44, :type :ok, :f :get, :key "1", :value "x 47 2 yx 43 2 yx 26 12 yx 47 7 y"} {:process 44, :type :invoke, :f :append, :key "9", :value "x 44 4 y"} {:process 47, :type :ok, :f :append, :key "3", :value "x 47 10 y"} {:process 47, :type :invoke, :f :append, :key "7", :value "x 47 11 y"} {:process 32, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 yx 40 1 yx 26 17 yx 47 9 y"} {:process 32, :type :invoke, :f :append, :key "0", :value "x 32 5 y"} {:process 29, :type :ok, :f :append, :key "5", :value "x 29 2 y"} {:process 29, :type :invoke, :f :append, :key "1", :value "x 29 3 y"} {:process 47, :type :ok, :f :append, :key "7", :value "x 47 11 y"} {:process 47, :type :invoke, :f :append, :key "4", :value "x 47 12 y"} {:process 49, :type :ok, :f :append, :key "0", :value "x 49 5 y"} {:process 49, :type :invoke, :f :append, :key "2", :value "x 49 6 y"} {:process 47, :type :ok, :f :append, :key "4", :value "x 47 12 y"} {:process 47, :type :invoke, :f :get, :key "2", :value nil} {:process 49, :type :ok, :f :append, :key "2", :value "x 49 6 y"} {:process 49, :type :invoke, :f :get, :key "1", :value nil} {:process 49, :type :ok, :f :get, :key "1", :value "x 47 2 yx 43 2 yx 26 12 yx 47 7 yx 36 1 y"} {:process 49, :type :invoke, :f :get, :key "4", :value nil} {:process 47, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 yx 40 1 yx 26 17 yx 47 9 yx 49 6 y"} {:process 47, :type :invoke, :f :append, :key "2", :value "x 47 13 y"} {:process 36, :type :ok, :f :get, :key "0", :value "x 10 3 yx 45 7 y"} {:process 36, :type :invoke, :f :get, :key "2", :value nil} {:process 36, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 yx 40 1 y"} {:process 36, :type :invoke, :f :append, :key "1", :value "x 36 4 y"} {:process 47, :type :ok, :f :append, :key "2", :value "x 47 13 y"} {:process 47, :type :invoke, :f :append, :key "4", :value "x 47 14 y"} {:process 47, :type :ok, :f :append, :key "4", :value "x 47 14 y"} {:process 47, :type :invoke, :f :append, :key "8", :value "x 47 15 y"} {:process 7, :type :ok, :f :append, :key "4", :value "x 7 3 y"} {:process 7, :type :invoke, :f :append, :key "8", :value "x 7 4 y"} {:process 47, :type :ok, :f :append, :key "8", :value "x 47 15 y"} {:process 47, :type :invoke, :f :get, :key "2", :value nil} {:process 7, :type :ok, :f :append, :key "8", :value "x 7 4 y"} {:process 7, :type :invoke, :f :get, :key "5", :value nil} {:process 47, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 yx 40 1 yx 26 17 yx 47 9 yx 49 6 yx 47 13 y"} {:process 47, :type :invoke, :f :append, :key "8", :value "x 47 16 y"} {:process 7, :type :ok, :f :get, :key "5", :value "x 43 4 yx 21 0 yx 47 5 yx 26 13 yx 44 2 yx 32 4 yx 29 2 y"} {:process 7, :type :invoke, :f :append, :key "2", :value "x 7 5 y"} {:process 7, :type :ok, :f :append, :key "2", :value "x 7 5 y"} {:process 7, :type :invoke, :f :get, :key "7", :value nil} {:process 47, :type :ok, :f :append, :key "8", :value "x 47 16 y"} {:process 47, :type :invoke, :f :append, :key "7", :value "x 47 17 y"} {:process 7, :type :ok, :f :get, :key "7", :value "x 38 1 yx 38 2 yx 43 0 yx 14 2 yx 6 4 yx 20 0 yx 45 4 yx 26 9 yx 39 1 yx 22 2 yx 47 11 y"} {:process 7, :type :invoke, :f :get, :key "9", :value nil} {:process 14, :type :ok, :f :append, :key "0", :value "x 14 5 y"} {:process 14, :type :invoke, :f :get, :key "6", :value nil} {:process 15, :type :ok, :f :append, :key "3", :value "x 15 0 y"} {:process 15, :type :invoke, :f :append, :key "4", :value "x 15 1 y"} {:process 47, :type :ok, :f :append, :key "7", :value "x 47 17 y"} {:process 47, :type :invoke, :f :append, :key "1", :value "x 47 18 y"} {:process 14, :type :ok, :f :get, :key "6", :value "x 42 5 yx 26 8 yx 26 11 yx 26 16 yx 36 2 yx 47 8 yx 36 3 y"} {:process 14, :type :invoke, :f :append, :key "9", :value "x 14 6 y"} {:process 15, :type :ok, :f :append, :key "4", :value "x 15 1 y"} {:process 15, :type :invoke, :f :append, :key "5", :value "x 15 2 y"} {:process 14, :type :ok, :f :append, :key "9", :value "x 14 6 y"} {:process 14, :type :invoke, :f :get, :key "1", :value nil} {:process 34, :type :ok, :f :append, :key "5", :value "x 34 2 y"} {:process 34, :type :invoke, :f :put, :key "8", :value "x 34 3 y"} {:process 35, :type :ok, :f :append, :key "6", :value "x 35 7 y"} {:process 35, :type :invoke, :f :put, :key "7", :value "x 35 8 y"} {:process 49, :type :ok, :f :get, :key "4", :value "x 24 0 yx 25 7 yx 7 3 yx 14 3 yx 49 4 yx 47 4 yx 21 1 yx 26 15 yx 47 12 yx 47 14 yx 15 1 y"} {:process 49, :type :invoke, :f :put, :key "1", :value "x 49 7 y"} {:process 15, :type :ok, :f :append, :key "5", :value "x 15 2 y"} {:process 15, :type :invoke, :f :get, :key "6", :value nil} {:process 39, :type :ok, :f :append, :key "7", :value "x 39 2 y"} {:process 39, :type :invoke, :f :get, :key "1", :value nil} {:process 15, :type :ok, :f :get, :key "6", :value "x 42 5 yx 26 8 yx 26 11 yx 26 16 yx 36 2 yx 47 8 yx 36 3 yx 35 7 y"} {:process 15, :type :invoke, :f :append, :key "6", :value "x 15 3 y"} {:process 39, :type :ok, :f :get, :key "1", :value "x 47 2 yx 43 2 yx 26 12 yx 47 7 yx 36 1 y"} {:process 39, :type :invoke, :f :append, :key "2", :value "x 39 3 y"} {:process 13, :type :ok, :f :append, :key "6", :value "x 13 1 y"} {:process 13, :type :invoke, :f :append, :key "1", :value "x 13 2 y"} {:process 7, :type :ok, :f :get, :key "9", :value "x 47 6 y"} {:process 7, :type :invoke, :f :get, :key "2", :value nil} {:process 14, :type :ok, :f :get, :key "1", :value "x 47 2 yx 43 2 yx 26 12 yx 47 7 y"} {:process 14, :type :invoke, :f :get, :key "5", :value nil} {:process 14, :type :ok, :f :get, :key "5", :value "x 43 4 yx 21 0 yx 47 5 yx 26 13 y"} {:process 14, :type :invoke, :f :append, :key "6", :value "x 14 7 y"} {:process 7, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 yx 40 1 yx 26 17 yx 47 9 yx 49 6 yx 47 13 yx 7 5 y"} {:process 7, :type :invoke, :f :append, :key "8", :value "x 7 6 y"} {:process 35, :type :ok, :f :put, :key "7", :value "x 35 8 y"} {:process 35, :type :invoke, :f :get, :key "8", :value nil} {:process 35, :type :ok, :f :get, :key "8", :value "x 34 3 yx 33 0 yx 11 1 yx 41 0 y"} {:process 35, :type :invoke, :f :get, :key "5", :value nil} {:process 8, :type :ok, :f :append, :key "8", :value "x 8 3 y"} {:process 8, :type :invoke, :f :get, :key "9", :value nil} {:process 8, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 yx 44 3 yx 14 6 yx 27 3 yx 24 1 yx 44 4 y"} {:process 8, :type :invoke, :f :get, :key "1", :value nil} {:process 38, :type :ok, :f :append, :key "4", :value "x 38 3 y"} {:process 38, :type :invoke, :f :get, :key "4", :value nil} {:process 8, :type :ok, :f :get, :key "1", :value "x 49 7 yx 47 18 yx 36 4 y"} {:process 8, :type :invoke, :f :get, :key "5", :value nil} {:process 3, :type :ok, :f :append, :key "2", :value "x 3 5 y"} {:process 3, :type :invoke, :f :get, :key "6", :value nil} {:process 3, :type :ok, :f :get, :key "6", :value "x 42 5 yx 26 8 yx 26 11 yx 26 16 yx 36 2 yx 47 8 yx 36 3 yx 35 7 yx 13 1 yx 15 3 yx 37 1 yx 4 7 yx 14 7 y"} {:process 3, :type :invoke, :f :append, :key "5", :value "x 3 6 y"} {:process 8, :type :ok, :f :get, :key "5", :value "x 43 4 yx 21 0 yx 47 5 yx 26 13 yx 44 2 yx 32 4 yx 29 2 yx 34 2 yx 15 2 yx 25 9 yx 30 6 y"} {:process 8, :type :invoke, :f :get, :key "2", :value nil} {:process 8, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 yx 40 1 yx 26 17 yx 47 9 yx 49 6 yx 47 13 yx 7 5 yx 39 3 yx 3 5 yx 43 5 y"} {:process 8, :type :invoke, :f :get, :key "4", :value nil} {:process 8, :type :ok, :f :get, :key "4", :value "x 16 0 yx 48 0 yx 0 0 yx 22 3 y"} {:process 8, :type :invoke, :f :append, :key "8", :value "x 8 4 y"} {:process 3, :type :ok, :f :append, :key "5", :value "x 3 6 y"} {:process 3, :type :invoke, :f :get, :key "4", :value nil} {:process 3, :type :ok, :f :get, :key "4", :value "x 16 0 yx 48 0 yx 0 0 yx 22 3 y"} {:process 3, :type :invoke, :f :get, :key "3", :value nil} {:process 31, :type :ok, :f :put, :key "0", :value "x 31 9 y"} {:process 31, :type :invoke, :f :get, :key "8", :value nil} {:process 8, :type :ok, :f :append, :key "8", :value "x 8 4 y"} {:process 8, :type :invoke, :f :append, :key "8", :value "x 8 5 y"} {:process 31, :type :ok, :f :get, :key "8", :value "x 34 3 yx 33 0 yx 11 1 yx 41 0 yx 8 3 yx 8 4 y"} {:process 31, :type :invoke, :f :append, :key "5", :value "x 31 10 y"} {:process 26, :type :ok, :f :append, :key "2", :value "x 26 17 y"} {:process 26, :type :invoke, :f :append, :key "4", :value "x 26 18 y"} {:process 3, :type :ok, :f :get, :key "3", :value "x 45 5 yx 45 6 yx 43 1 yx 25 8 yx 21 2 yx 47 10 yx 9 3 y"} {:process 3, :type :invoke, :f :append, :key "9", :value "x 3 7 y"} {:process 43, :type :ok, :f :append, :key "2", :value "x 43 5 y"} {:process 43, :type :invoke, :f :append, :key "3", :value "x 43 6 y"} {:process 8, :type :ok, :f :append, :key "8", :value "x 8 5 y"} {:process 8, :type :invoke, :f :get, :key "8", :value nil} {:process 31, :type :ok, :f :append, :key "5", :value "x 31 10 y"} {:process 31, :type :invoke, :f :get, :key "6", :value nil} {:process 43, :type :ok, :f :append, :key "3", :value "x 43 6 y"} {:process 43, :type :invoke, :f :append, :key "1", :value "x 43 7 y"} {:process 8, :type :ok, :f :get, :key "8", :value "x 34 3 yx 33 0 yx 11 1 yx 41 0 yx 8 3 yx 8 4 yx 8 5 y"} {:process 8, :type :invoke, :f :get, :key "7", :value nil} {:process 8, :type :ok, :f :get, :key "7", :value "x 35 8 yx 18 1 yx 45 9 y"} {:process 8, :type :invoke, :f :get, :key "5", :value nil} {:process 31, :type :ok, :f :get, :key "6", :value "x 42 5 yx 26 8 yx 26 11 yx 26 16 yx 36 2 yx 47 8 yx 36 3 yx 35 7 yx 13 1 yx 15 3 yx 37 1 yx 4 7 yx 14 7 y"} {:process 31, :type :invoke, :f :get, :key "9", :value nil} {:process 31, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 yx 44 3 yx 14 6 yx 27 3 yx 24 1 yx 44 4 y"} {:process 31, :type :invoke, :f :get, :key "4", :value nil} {:process 8, :type :ok, :f :get, :key "5", :value "x 43 4 yx 21 0 yx 47 5 yx 26 13 yx 44 2 yx 32 4 yx 29 2 yx 34 2 yx 15 2 yx 25 9 yx 30 6 yx 3 6 yx 31 10 y"} {:process 8, :type :invoke, :f :get, :key "3", :value nil} {:process 31, :type :ok, :f :get, :key "4", :value "x 16 0 yx 48 0 yx 0 0 yx 22 3 y"} {:process 31, :type :invoke, :f :append, :key "4", :value "x 31 11 y"} {:process 3, :type :ok, :f :append, :key "9", :value "x 3 7 y"} {:process 3, :type :invoke, :f :append, :key "3", :value "x 3 8 y"} {:process 43, :type :ok, :f :append, :key "1", :value "x 43 7 y"} {:process 43, :type :invoke, :f :append, :key "5", :value "x 43 8 y"} {:process 35, :type :ok, :f :get, :key "5", :value "x 43 4 yx 21 0 yx 47 5 yx 26 13 y"} {:process 35, :type :invoke, :f :append, :key "1", :value "x 35 9 y"} {:process 38, :type :ok, :f :get, :key "4", :value "x 24 0 yx 25 7 yx 7 3 yx 14 3 yx 49 4 yx 47 4 yx 21 1 yx 26 15 yx 47 12 yx 47 14 yx 15 1 y"} {:process 38, :type :invoke, :f :get, :key "1", :value nil} {:process 3, :type :ok, :f :append, :key "3", :value "x 3 8 y"} {:process 3, :type :invoke, :f :append, :key "0", :value "x 3 9 y"} {:process 8, :type :ok, :f :get, :key "3", :value "x 45 5 yx 45 6 yx 43 1 yx 25 8 yx 21 2 yx 47 10 yx 9 3 yx 43 6 yx 3 8 y"} {:process 8, :type :invoke, :f :get, :key "0", :value nil} {:process 38, :type :ok, :f :get, :key "1", :value "x 47 2 yx 43 2 yx 26 12 yx 47 7 yx 36 1 y"} {:process 38, :type :invoke, :f :append, :key "0", :value "x 38 4 y"} {:process 31, :type :ok, :f :append, :key "4", :value "x 31 11 y"} {:process 31, :type :invoke, :f :append, :key "4", :value "x 31 12 y"} {:process 27, :type :ok, :f :append, :key "9", :value "x 27 3 y"} {:process 27, :type :invoke, :f :append, :key "8", :value "x 27 4 y"} {:process 9, :type :ok, :f :append, :key "3", :value "x 9 3 y"} {:process 9, :type :invoke, :f :append, :key "6", :value "x 9 4 y"} {:process 43, :type :ok, :f :append, :key "5", :value "x 43 8 y"} {:process 43, :type :invoke, :f :get, :key "2", :value nil} {:process 3, :type :ok, :f :append, :key "0", :value "x 3 9 y"} {:process 3, :type :invoke, :f :get, :key "6", :value nil} {:process 31, :type :ok, :f :append, :key "4", :value "x 31 12 y"} {:process 31, :type :invoke, :f :append, :key "4", :value "x 31 13 y"} {:process 3, :type :ok, :f :get, :key "6", :value "x 42 5 yx 26 8 yx 26 11 yx 26 16 yx 36 2 yx 47 8 yx 36 3 yx 35 7 yx 13 1 yx 15 3 yx 37 1 yx 4 7 yx 14 7 y"} {:process 3, :type :invoke, :f :append, :key "1", :value "x 3 10 y"} {:process 31, :type :ok, :f :append, :key "4", :value "x 31 13 y"} {:process 31, :type :invoke, :f :append, :key "4", :value "x 31 14 y"} {:process 9, :type :ok, :f :append, :key "6", :value "x 9 4 y"} {:process 9, :type :invoke, :f :append, :key "9", :value "x 9 5 y"} {:process 28, :type :ok, :f :append, :key "0", :value "x 28 1 y"} {:process 31, :type :ok, :f :append, :key "4", :value "x 31 14 y"} {:process 28, :type :invoke, :f :append, :key "4", :value "x 28 2 y"} {:process 31, :type :invoke, :f :get, :key "0", :value nil} {:process 31, :type :ok, :f :get, :key "0", :value "x 10 3 yx 45 7 yx 32 5 yx 49 5 yx 14 5 yx 21 3 yx 28 1 yx 1 1 yx 3 9 y"} {:process 31, :type :invoke, :f :append, :key "3", :value "x 31 15 y"} {:process 8, :type :ok, :f :get, :key "0", :value "x 10 3 yx 45 7 yx 32 5 yx 49 5 yx 14 5 yx 21 3 yx 28 1 yx 1 1 yx 3 9 y"} {:process 8, :type :invoke, :f :append, :key "0", :value "x 8 6 y"} {:process 9, :type :ok, :f :append, :key "9", :value "x 9 5 y"} {:process 9, :type :invoke, :f :append, :key "1", :value "x 9 6 y"} {:process 31, :type :ok, :f :append, :key "3", :value "x 31 15 y"} {:process 31, :type :invoke, :f :get, :key "3", :value nil} {:process 7, :type :ok, :f :append, :key "8", :value "x 7 6 y"} {:process 7, :type :invoke, :f :append, :key "4", :value "x 7 7 y"} {:process 43, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 yx 40 1 yx 26 17 yx 47 9 yx 49 6 yx 47 13 yx 7 5 yx 39 3 yx 3 5 yx 43 5 y"} {:process 43, :type :invoke, :f :get, :key "2", :value nil} {:process 40, :type :ok, :f :append, :key "2", :value "x 40 1 y"} {:process 40, :type :invoke, :f :append, :key "0", :value "x 40 2 y"} {:process 43, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 yx 40 1 yx 26 17 yx 47 9 yx 49 6 yx 47 13 yx 7 5 yx 39 3 yx 3 5 yx 43 5 y"} {:process 43, :type :invoke, :f :append, :key "1", :value "x 43 9 y"} {:process 33, :type :ok, :f :append, :key "8", :value "x 33 0 y"} {:process 33, :type :invoke, :f :get, :key "2", :value nil} {:process 9, :type :ok, :f :append, :key "1", :value "x 9 6 y"} {:process 9, :type :invoke, :f :put, :key "4", :value "x 9 7 y"} {:process 7, :type :ok, :f :append, :key "4", :value "x 7 7 y"} {:process 7, :type :invoke, :f :append, :key "7", :value "x 7 8 y"} {:process 33, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 yx 40 1 yx 26 17 yx 47 9 yx 49 6 yx 47 13 yx 7 5 yx 39 3 yx 3 5 yx 43 5 y"} {:process 33, :type :invoke, :f :append, :key "0", :value "x 33 1 y"} {:process 40, :type :ok, :f :append, :key "0", :value "x 40 2 y"} {:process 40, :type :invoke, :f :append, :key "9", :value "x 40 3 y"} {:process 37, :type :ok, :f :append, :key "6", :value "x 37 1 y"} {:process 37, :type :invoke, :f :append, :key "1", :value "x 37 2 y"} {:process 33, :type :ok, :f :append, :key "0", :value "x 33 1 y"} {:process 33, :type :invoke, :f :append, :key "8", :value "x 33 2 y"} {:process 7, :type :ok, :f :append, :key "7", :value "x 7 8 y"} {:process 7, :type :invoke, :f :append, :key "4", :value "x 7 9 y"} {:process 46, :type :ok, :f :put, :key "0", :value "x 46 1 y"} {:process 46, :type :invoke, :f :get, :key "0", :value nil} {:process 46, :type :ok, :f :get, :key "0", :value "x 10 3 yx 45 7 yx 32 5 yx 49 5 yx 14 5 yx 21 3 yx 28 1 yx 1 1 yx 3 9 yx 40 2 yx 33 1 y"} {:process 46, :type :invoke, :f :get, :key "4", :value nil} {:process 37, :type :ok, :f :append, :key "1", :value "x 37 2 y"} {:process 37, :type :invoke, :f :append, :key "3", :value "x 37 3 y"} {:process 46, :type :ok, :f :get, :key "4", :value "x 9 7 y"} {:process 46, :type :invoke, :f :append, :key "8", :value "x 46 2 y"} {:process 33, :type :ok, :f :append, :key "8", :value "x 33 2 y"} {:process 33, :type :invoke, :f :get, :key "3", :value nil} {:process 19, :type :ok, :f :append, :key "1", :value "x 19 3 y"} {:process 19, :type :invoke, :f :get, :key "1", :value nil} {:process 33, :type :ok, :f :get, :key "3", :value "x 45 5 yx 45 6 yx 43 1 yx 25 8 yx 21 2 yx 47 10 yx 9 3 yx 43 6 yx 3 8 yx 31 15 y"} {:process 33, :type :invoke, :f :get, :key "8", :value nil} {:process 7, :type :ok, :f :append, :key "4", :value "x 7 9 y"} {:process 7, :type :invoke, :f :get, :key "3", :value nil} {:process 46, :type :ok, :f :append, :key "8", :value "x 46 2 y"} {:process 46, :type :invoke, :f :append, :key "1", :value "x 46 3 y"} {:process 7, :type :ok, :f :get, :key "3", :value "x 45 5 yx 45 6 yx 43 1 yx 25 8 yx 21 2 yx 47 10 yx 9 3 yx 43 6 yx 3 8 yx 31 15 y"} {:process 7, :type :invoke, :f :append, :key "2", :value "x 7 10 y"} {:process 19, :type :ok, :f :get, :key "1", :value "x 49 7 yx 47 18 yx 36 4 yx 43 7 yx 3 10 yx 9 6 yx 37 2 y"} {:process 19, :type :invoke, :f :append, :key "4", :value "x 19 4 y"} {:process 23, :type :ok, :f :append, :key "1", :value "x 23 4 y"} {:process 23, :type :invoke, :f :append, :key "3", :value "x 23 5 y"} {:process 37, :type :ok, :f :append, :key "3", :value "x 37 3 y"} {:process 37, :type :invoke, :f :get, :key "5", :value nil} {:process 11, :type :ok, :f :append, :key "8", :value "x 11 1 y"} {:process 11, :type :invoke, :f :append, :key "7", :value "x 11 2 y"} {:process 16, :type :ok, :f :put, :key "4", :value "x 16 0 y"} {:process 16, :type :invoke, :f :append, :key "2", :value "x 16 1 y"} {:process 33, :type :ok, :f :get, :key "8", :value "x 34 3 yx 33 0 yx 11 1 yx 41 0 yx 8 3 yx 8 4 yx 8 5 yx 27 4 yx 7 6 yx 33 2 yx 46 2 y"} {:process 33, :type :invoke, :f :get, :key "0", :value nil} {:process 37, :type :ok, :f :get, :key "5", :value "x 43 4 yx 21 0 yx 47 5 yx 26 13 yx 44 2 yx 32 4 yx 29 2 yx 34 2 yx 15 2 yx 25 9 yx 30 6 yx 3 6 yx 31 10 yx 43 8 y"} {:process 37, :type :invoke, :f :append, :key "7", :value "x 37 4 y"} {:process 7, :type :ok, :f :append, :key "2", :value "x 7 10 y"} {:process 7, :type :invoke, :f :append, :key "9", :value "x 7 11 y"} {:process 16, :type :ok, :f :append, :key "2", :value "x 16 1 y"} {:process 16, :type :invoke, :f :append, :key "7", :value "x 16 2 y"} {:process 11, :type :ok, :f :append, :key "7", :value "x 11 2 y"} {:process 11, :type :invoke, :f :get, :key "1", :value nil} {:process 46, :type :ok, :f :append, :key "1", :value "x 46 3 y"} {:process 46, :type :invoke, :f :append, :key "4", :value "x 46 4 y"} {:process 11, :type :ok, :f :get, :key "1", :value "x 49 7 yx 47 18 yx 36 4 yx 43 7 yx 3 10 yx 9 6 yx 37 2 yx 46 3 y"} {:process 11, :type :invoke, :f :append, :key "1", :value "x 11 3 y"} {:process 33, :type :ok, :f :get, :key "0", :value "x 10 3 yx 45 7 yx 32 5 yx 49 5 yx 14 5 yx 21 3 yx 28 1 yx 1 1 yx 3 9 yx 40 2 yx 33 1 y"} {:process 33, :type :invoke, :f :append, :key "6", :value "x 33 3 y"} {:process 19, :type :ok, :f :append, :key "4", :value "x 19 4 y"} {:process 19, :type :invoke, :f :append, :key "9", :value "x 19 5 y"} {:process 11, :type :ok, :f :append, :key "1", :value "x 11 3 y"} {:process 11, :type :invoke, :f :append, :key "9", :value "x 11 4 y"} {:process 16, :type :ok, :f :append, :key "7", :value "x 16 2 y"} {:process 7, :type :ok, :f :append, :key "9", :value "x 7 11 y"} {:process 16, :type :invoke, :f :get, :key "0", :value nil} {:process 7, :type :invoke, :f :append, :key "2", :value "x 7 12 y"} {:process 46, :type :ok, :f :append, :key "4", :value "x 46 4 y"} {:process 46, :type :invoke, :f :append, :key "9", :value "x 46 5 y"} {:process 19, :type :ok, :f :append, :key "9", :value "x 19 5 y"} {:process 19, :type :invoke, :f :put, :key "7", :value "x 19 6 y"} {:process 48, :type :ok, :f :append, :key "4", :value "x 48 0 y"} {:process 48, :type :invoke, :f :append, :key "8", :value "x 48 1 y"} {:process 29, :type :ok, :f :append, :key "1", :value "x 29 3 y"} {:process 29, :type :invoke, :f :append, :key "7", :value "x 29 4 y"} {:process 7, :type :ok, :f :append, :key "2", :value "x 7 12 y"} {:process 7, :type :invoke, :f :append, :key "7", :value "x 7 13 y"} {:process 11, :type :ok, :f :append, :key "9", :value "x 11 4 y"} {:process 7, :type :ok, :f :append, :key "7", :value "x 7 13 y"} {:process 7, :type :invoke, :f :append, :key "0", :value "x 7 14 y"} {:process 11, :type :invoke, :f :get, :key "3", :value nil} {:process 46, :type :ok, :f :append, :key "9", :value "x 46 5 y"} {:process 46, :type :invoke, :f :get, :key "6", :value nil} {:process 46, :type :ok, :f :get, :key "6", :value "x 42 5 yx 26 8 yx 26 11 yx 26 16 yx 36 2 yx 47 8 yx 36 3 yx 35 7 yx 13 1 yx 15 3 yx 37 1 yx 4 7 yx 14 7 yx 9 4 yx 33 3 y"} {:process 46, :type :invoke, :f :put, :key "8", :value "x 46 6 y"} {:process 29, :type :ok, :f :append, :key "7", :value "x 29 4 y"} {:process 29, :type :invoke, :f :append, :key "4", :value "x 29 5 y"} {:process 41, :type :ok, :f :append, :key "8", :value "x 41 0 y"} {:process 41, :type :invoke, :f :get, :key "4", :value nil} {:process 6, :type :ok, :f :append, :key "9", :value "x 6 5 y"} {:process 6, :type :invoke, :f :get, :key "2", :value nil} {:process 31, :type :ok, :f :get, :key "3", :value "x 45 5 yx 45 6 yx 43 1 yx 25 8 yx 21 2 yx 47 10 y"} {:process 31, :type :invoke, :f :append, :key "9", :value "x 31 16 y"} {:process 7, :type :ok, :f :append, :key "0", :value "x 7 14 y"} {:process 7, :type :invoke, :f :get, :key "6", :value nil} {:process 29, :type :ok, :f :append, :key "4", :value "x 29 5 y"} {:process 29, :type :invoke, :f :get, :key "6", :value nil} {:process 6, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 yx 40 1 yx 26 17 yx 47 9 yx 49 6 yx 47 13 yx 7 5 yx 39 3 yx 3 5 yx 43 5 yx 7 10 yx 16 1 yx 7 12 y"} {:process 6, :type :invoke, :f :append, :key "9", :value "x 6 6 y"} {:process 46, :type :ok, :f :put, :key "8", :value "x 46 6 y"} {:process 46, :type :invoke, :f :get, :key "5", :value nil} {:process 18, :type :ok, :f :append, :key "7", :value "x 18 1 y"} {:process 18, :type :invoke, :f :append, :key "0", :value "x 18 2 y"} {:process 29, :type :ok, :f :get, :key "6", :value "x 42 5 yx 26 8 yx 26 11 yx 26 16 yx 36 2 yx 47 8 yx 36 3 yx 35 7 yx 13 1 yx 15 3 yx 37 1 yx 4 7 yx 14 7 yx 9 4 yx 33 3 y"} {:process 29, :type :invoke, :f :append, :key "2", :value "x 29 6 y"} {:process 16, :type :ok, :f :get, :key "0", :value "x 10 3 yx 45 7 y"} {:process 16, :type :invoke, :f :get, :key "1", :value nil} {:process 11, :type :ok, :f :get, :key "3", :value "x 45 5 yx 45 6 yx 43 1 yx 25 8 yx 21 2 y"} {:process 11, :type :invoke, :f :append, :key "3", :value "x 11 5 y"} {:process 41, :type :ok, :f :get, :key "4", :value "x 9 7 yx 7 9 yx 19 4 yx 46 4 y"} {:process 41, :type :invoke, :f :append, :key "2", :value "x 41 1 y"} {:process 46, :type :ok, :f :get, :key "5", :value "x 43 4 yx 21 0 yx 47 5 yx 26 13 y"} {:process 46, :type :invoke, :f :append, :key "5", :value "x 46 7 y"} {:process 7, :type :ok, :f :get, :key "6", :value "x 42 5 yx 26 8 yx 26 11 yx 26 16 y"} {:process 7, :type :invoke, :f :get, :key "5", :value nil} {:process 7, :type :ok, :f :get, :key "5", :value "x 43 4 yx 21 0 yx 47 5 yx 26 13 y"} {:process 7, :type :invoke, :f :append, :key "9", :value "x 7 15 y"} {:process 16, :type :ok, :f :get, :key "1", :value "x 49 7 yx 47 18 yx 36 4 yx 43 7 yx 3 10 yx 9 6 yx 37 2 yx 46 3 yx 11 3 y"} {:process 16, :type :invoke, :f :get, :key "9", :value nil} {:process 16, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 yx 44 3 yx 14 6 yx 27 3 yx 24 1 yx 44 4 yx 3 7 yx 9 5 yx 7 11 yx 19 5 yx 11 4 yx 46 5 y"} {:process 16, :type :invoke, :f :append, :key "3", :value "x 16 3 y"} {:process 38, :type :ok, :f :append, :key "0", :value "x 38 4 y"} {:process 38, :type :invoke, :f :get, :key "4", :value nil} {:process 24, :type :ok, :f :append, :key "9", :value "x 24 1 y"} {:process 24, :type :invoke, :f :append, :key "5", :value "x 24 2 y"} {:process 31, :type :ok, :f :append, :key "9", :value "x 31 16 y"} {:process 31, :type :invoke, :f :get, :key "2", :value nil} {:process 31, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 yx 40 1 yx 26 17 yx 47 9 yx 49 6 yx 47 13 yx 7 5 yx 39 3 yx 3 5 yx 43 5 yx 7 10 yx 16 1 yx 7 12 y"} {:process 31, :type :invoke, :f :get, :key "8", :value nil} {:process 31, :type :ok, :f :get, :key "8", :value "x 46 6 y"} {:process 31, :type :invoke, :f :get, :key "3", :value nil} {:process 10, :type :ok, :f :append, :key "8", :value "x 10 4 y"} {:process 10, :type :invoke, :f :append, :key "1", :value "x 10 5 y"} {:process 24, :type :ok, :f :append, :key "5", :value "x 24 2 y"} {:process 24, :type :invoke, :f :append, :key "0", :value "x 24 3 y"} {:process 41, :type :ok, :f :append, :key "2", :value "x 41 1 y"} {:process 41, :type :invoke, :f :append, :key "1", :value "x 41 2 y"} {:process 31, :type :ok, :f :get, :key "3", :value "x 45 5 yx 45 6 yx 43 1 yx 25 8 yx 21 2 yx 47 10 yx 9 3 yx 43 6 yx 3 8 yx 31 15 yx 37 3 y"} {:process 31, :type :invoke, :f :append, :key "0", :value "x 31 17 y"} {:process 10, :type :ok, :f :append, :key "1", :value "x 10 5 y"} {:process 10, :type :invoke, :f :append, :key "8", :value "x 10 6 y"} {:process 21, :type :ok, :f :append, :key "0", :value "x 21 3 y"} {:process 21, :type :invoke, :f :append, :key "9", :value "x 21 4 y"} {:process 41, :type :ok, :f :append, :key "1", :value "x 41 2 y"} {:process 41, :type :invoke, :f :get, :key "3", :value nil} {:process 31, :type :ok, :f :append, :key "0", :value "x 31 17 y"} {:process 31, :type :invoke, :f :put, :key "4", :value "x 31 18 y"} {:process 17, :type :ok, :f :append, :key "8", :value "x 17 6 y"} {:process 17, :type :invoke, :f :append, :key "9", :value "x 17 7 y"} {:process 19, :type :ok, :f :put, :key "7", :value "x 19 6 y"} {:process 19, :type :invoke, :f :get, :key "2", :value nil} {:process 10, :type :ok, :f :append, :key "8", :value "x 10 6 y"} {:process 10, :type :invoke, :f :append, :key "5", :value "x 10 7 y"} {:process 21, :type :ok, :f :append, :key "9", :value "x 21 4 y"} {:process 21, :type :invoke, :f :get, :key "9", :value nil} {:process 19, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 yx 40 1 yx 26 17 yx 47 9 yx 49 6 yx 47 13 yx 7 5 yx 39 3 yx 3 5 yx 43 5 yx 7 10 yx 16 1 yx 7 12 yx 41 1 y"} {:process 19, :type :invoke, :f :append, :key "0", :value "x 19 7 y"} {:process 41, :type :ok, :f :get, :key "3", :value "x 45 5 yx 45 6 yx 43 1 yx 25 8 yx 21 2 yx 47 10 yx 9 3 yx 43 6 yx 3 8 yx 31 15 yx 37 3 y"} {:process 41, :type :invoke, :f :append, :key "1", :value "x 41 3 y"} {:process 10, :type :ok, :f :append, :key "5", :value "x 10 7 y"} {:process 10, :type :invoke, :f :get, :key "0", :value nil} {:process 19, :type :ok, :f :append, :key "0", :value "x 19 7 y"} {:process 19, :type :invoke, :f :append, :key "3", :value "x 19 8 y"} {:process 21, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 yx 44 3 yx 14 6 yx 27 3 yx 24 1 yx 44 4 yx 3 7 yx 9 5 yx 7 11 yx 19 5 yx 11 4 yx 46 5 yx 31 16 yx 21 4 y"} {:process 21, :type :invoke, :f :append, :key "4", :value "x 21 5 y"} {:process 17, :type :ok, :f :append, :key "9", :value "x 17 7 y"} {:process 17, :type :invoke, :f :append, :key "9", :value "x 17 8 y"} {:process 10, :type :ok, :f :get, :key "0", :value "x 10 3 yx 45 7 yx 32 5 yx 49 5 yx 14 5 yx 21 3 yx 28 1 yx 1 1 yx 3 9 yx 40 2 yx 33 1 yx 7 14 yx 38 4 yx 24 3 yx 31 17 yx 19 7 y"} {:process 10, :type :invoke, :f :put, :key "3", :value "x 10 8 y"} {:process 41, :type :ok, :f :append, :key "1", :value "x 41 3 y"} {:process 41, :type :invoke, :f :get, :key "9", :value nil} {:process 19, :type :ok, :f :append, :key "3", :value "x 19 8 y"} {:process 19, :type :invoke, :f :append, :key "6", :value "x 19 9 y"} {:process 10, :type :ok, :f :put, :key "3", :value "x 10 8 y"} {:process 10, :type :invoke, :f :append, :key "5", :value "x 10 9 y"} {:process 38, :type :ok, :f :get, :key "4", :value "x 31 18 y"} {:process 38, :type :invoke, :f :append, :key "3", :value "x 38 5 y"} {:process 21, :type :ok, :f :append, :key "4", :value "x 21 5 y"} {:process 21, :type :invoke, :f :get, :key "0", :value nil} {:process 10, :type :ok, :f :append, :key "5", :value "x 10 9 y"} {:process 10, :type :invoke, :f :append, :key "1", :value "x 10 10 y"} {:process 19, :type :ok, :f :append, :key "6", :value "x 19 9 y"} {:process 19, :type :invoke, :f :get, :key "9", :value nil} {:process 19, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 yx 44 3 yx 14 6 yx 27 3 yx 24 1 yx 44 4 yx 3 7 yx 9 5 yx 7 11 yx 19 5 yx 11 4 yx 46 5 yx 31 16 yx 21 4 yx 17 7 yx 17 8 y"} {:process 19, :type :invoke, :f :get, :key "4", :value nil} {:process 21, :type :ok, :f :get, :key "0", :value "x 10 3 yx 45 7 yx 32 5 yx 49 5 yx 14 5 yx 21 3 yx 28 1 yx 1 1 yx 3 9 yx 40 2 yx 33 1 yx 7 14 yx 38 4 yx 24 3 yx 31 17 yx 19 7 y"} {:process 21, :type :invoke, :f :append, :key "0", :value "x 21 6 y"} {:process 21, :type :ok, :f :append, :key "0", :value "x 21 6 y"} {:process 21, :type :invoke, :f :append, :key "3", :value "x 21 7 y"} {:process 19, :type :ok, :f :get, :key "4", :value "x 31 18 yx 21 5 y"} {:process 19, :type :invoke, :f :get, :key "9", :value nil} {:process 10, :type :ok, :f :append, :key "1", :value "x 10 10 y"} {:process 10, :type :invoke, :f :get, :key "2", :value nil} {:process 29, :type :ok, :f :append, :key "2", :value "x 29 6 y"} {:process 29, :type :invoke, :f :append, :key "7", :value "x 29 7 y"} {:process 21, :type :ok, :f :append, :key "3", :value "x 21 7 y"} {:process 21, :type :invoke, :f :get, :key "3", :value nil} {:process 21, :type :ok, :f :get, :key "3", :value "x 10 8 yx 21 7 y"} {:process 21, :type :invoke, :f :get, :key "3", :value nil} {:process 34, :type :ok, :f :put, :key "8", :value "x 34 3 y"} {:process 34, :type :invoke, :f :get, :key "4", :value nil} {:process 29, :type :ok, :f :append, :key "7", :value "x 29 7 y"} {:process 29, :type :invoke, :f :append, :key "9", :value "x 29 8 y"} {:process 10, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 yx 40 1 yx 26 17 yx 47 9 yx 49 6 yx 47 13 yx 7 5 yx 39 3 yx 3 5 yx 43 5 yx 7 10 yx 16 1 yx 7 12 yx 41 1 yx 29 6 y"} {:process 10, :type :invoke, :f :get, :key "8", :value nil} {:process 21, :type :ok, :f :get, :key "3", :value "x 10 8 yx 21 7 y"} {:process 21, :type :invoke, :f :get, :key "5", :value nil} {:process 13, :type :ok, :f :append, :key "1", :value "x 13 2 y"} {:process 13, :type :invoke, :f :append, :key "2", :value "x 13 3 y"} {:process 34, :type :ok, :f :get, :key "4", :value "x 31 18 yx 21 5 y"} {:process 34, :type :invoke, :f :get, :key "0", :value nil} {:process 10, :type :ok, :f :get, :key "8", :value "x 46 6 yx 10 4 yx 17 6 yx 10 6 y"} {:process 10, :type :invoke, :f :get, :key "3", :value nil} {:process 41, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 yx 44 3 yx 14 6 yx 27 3 yx 24 1 yx 44 4 yx 3 7 yx 9 5 yx 7 11 yx 19 5 yx 11 4 yx 46 5 yx 31 16 yx 21 4 yx 17 7 yx 17 8 y"} {:process 41, :type :invoke, :f :get, :key "7", :value nil} {:process 41, :type :ok, :f :get, :key "7", :value "x 19 6 yx 29 7 y"} {:process 41, :type :invoke, :f :get, :key "5", :value nil} {:process 34, :type :ok, :f :get, :key "0", :value "x 10 3 yx 45 7 yx 32 5 yx 49 5 yx 14 5 yx 21 3 yx 28 1 yx 1 1 yx 3 9 yx 40 2 yx 33 1 yx 7 14 yx 38 4 yx 24 3 yx 31 17 yx 19 7 yx 21 6 y"} {:process 34, :type :invoke, :f :append, :key "7", :value "x 34 4 y"} {:process 10, :type :ok, :f :get, :key "3", :value "x 10 8 yx 21 7 y"} {:process 10, :type :invoke, :f :get, :key "5", :value nil} {:process 29, :type :ok, :f :append, :key "9", :value "x 29 8 y"} {:process 29, :type :invoke, :f :append, :key "5", :value "x 29 9 y"} {:process 10, :type :ok, :f :get, :key "5", :value "x 43 4 yx 21 0 yx 47 5 yx 26 13 yx 44 2 yx 32 4 yx 29 2 yx 34 2 yx 15 2 yx 25 9 yx 30 6 yx 3 6 yx 31 10 yx 43 8 yx 24 2 yx 10 7 yx 10 9 y"} {:process 10, :type :invoke, :f :get, :key "6", :value nil} {:process 13, :type :ok, :f :append, :key "2", :value "x 13 3 y"} {:process 13, :type :invoke, :f :append, :key "5", :value "x 13 4 y"} {:process 34, :type :ok, :f :append, :key "7", :value "x 34 4 y"} {:process 34, :type :invoke, :f :append, :key "0", :value "x 34 5 y"} {:process 13, :type :ok, :f :append, :key "5", :value "x 13 4 y"} {:process 13, :type :invoke, :f :append, :key "5", :value "x 13 5 y"} {:process 10, :type :ok, :f :get, :key "6", :value "x 42 5 yx 26 8 yx 26 11 yx 26 16 yx 36 2 yx 47 8 yx 36 3 yx 35 7 yx 13 1 yx 15 3 yx 37 1 yx 4 7 yx 14 7 yx 9 4 yx 33 3 yx 19 9 y"} {:process 10, :type :invoke, :f :append, :key "0", :value "x 10 11 y"} {:process 29, :type :ok, :f :append, :key "5", :value "x 29 9 y"} {:process 29, :type :invoke, :f :append, :key "1", :value "x 29 10 y"} {:process 47, :type :ok, :f :append, :key "1", :value "x 47 18 y"} {:process 47, :type :invoke, :f :get, :key "5", :value nil} {:process 13, :type :ok, :f :append, :key "5", :value "x 13 5 y"} {:process 13, :type :invoke, :f :append, :key "2", :value "x 13 6 y"} {:process 34, :type :ok, :f :append, :key "0", :value "x 34 5 y"} {:process 34, :type :invoke, :f :get, :key "1", :value nil} {:process 34, :type :ok, :f :get, :key "1", :value "x 49 7 yx 47 18 yx 36 4 yx 43 7 yx 3 10 yx 9 6 yx 37 2 yx 46 3 yx 11 3 yx 10 5 yx 41 2 yx 41 3 yx 43 9 yx 10 10 y"} {:process 34, :type :invoke, :f :get, :key "0", :value nil} {:process 47, :type :ok, :f :get, :key "5", :value "x 43 4 yx 21 0 yx 47 5 yx 26 13 yx 44 2 yx 32 4 yx 29 2 yx 34 2 yx 15 2 yx 25 9 yx 30 6 yx 3 6 yx 31 10 yx 43 8 yx 24 2 yx 10 7 yx 10 9 yx 13 4 yx 29 9 yx 13 5 y"} {:process 47, :type :invoke, :f :get, :key "9", :value nil} {:process 10, :type :ok, :f :append, :key "0", :value "x 10 11 y"} {:process 10, :type :invoke, :f :get, :key "3", :value nil} {:process 40, :type :ok, :f :append, :key "9", :value "x 40 3 y"} {:process 40, :type :invoke, :f :append, :key "0", :value "x 40 4 y"} {:process 34, :type :ok, :f :get, :key "0", :value "x 10 3 yx 45 7 yx 32 5 yx 49 5 yx 14 5 yx 21 3 yx 28 1 yx 1 1 yx 3 9 yx 40 2 yx 33 1 yx 7 14 yx 38 4 yx 24 3 yx 31 17 yx 19 7 yx 21 6 yx 34 5 yx 10 11 y"} {:process 34, :type :invoke, :f :get, :key "9", :value nil} {:process 29, :type :ok, :f :append, :key "1", :value "x 29 10 y"} {:process 29, :type :invoke, :f :append, :key "3", :value "x 29 11 y"} {:process 10, :type :ok, :f :get, :key "3", :value "x 10 8 yx 21 7 y"} {:process 10, :type :invoke, :f :append, :key "1", :value "x 10 12 y"} {:process 47, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 yx 44 3 yx 14 6 yx 27 3 yx 24 1 yx 44 4 yx 3 7 yx 9 5 yx 7 11 yx 19 5 yx 11 4 yx 46 5 yx 31 16 yx 21 4 yx 17 7 yx 17 8 yx 29 8 yx 40 3 y"} {:process 47, :type :invoke, :f :get, :key "6", :value nil} {:process 47, :type :ok, :f :get, :key "6", :value "x 42 5 yx 26 8 yx 26 11 yx 26 16 yx 36 2 yx 47 8 yx 36 3 yx 35 7 yx 13 1 yx 15 3 yx 37 1 yx 4 7 yx 14 7 yx 9 4 yx 33 3 yx 19 9 y"} {:process 47, :type :invoke, :f :append, :key "9", :value "x 47 19 y"} {:process 19, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 yx 44 3 yx 14 6 yx 27 3 yx 24 1 yx 44 4 yx 3 7 yx 9 5 yx 7 11 yx 19 5 yx 11 4 yx 46 5 yx 31 16 yx 21 4 yx 17 7 yx 17 8 yx 29 8 y"} {:process 19, :type :invoke, :f :append, :key "9", :value "x 19 10 y"} {:process 13, :type :ok, :f :append, :key "2", :value "x 13 6 y"} {:process 13, :type :invoke, :f :get, :key "9", :value nil} {:process 47, :type :ok, :f :append, :key "9", :value "x 47 19 y"} {:process 47, :type :invoke, :f :append, :key "1", :value "x 47 20 y"} {:process 13, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 yx 44 3 yx 14 6 yx 27 3 yx 24 1 yx 44 4 yx 3 7 yx 9 5 yx 7 11 yx 19 5 yx 11 4 yx 46 5 yx 31 16 yx 21 4 yx 17 7 yx 17 8 yx 29 8 yx 40 3 yx 47 19 y"} {:process 13, :type :invoke, :f :append, :key "6", :value "x 13 7 y"} {:process 34, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 yx 44 3 yx 14 6 yx 27 3 yx 24 1 yx 44 4 yx 3 7 yx 9 5 yx 7 11 yx 19 5 yx 11 4 yx 46 5 yx 31 16 yx 21 4 yx 17 7 yx 17 8 yx 29 8 yx 40 3 yx 47 19 y"} {:process 34, :type :invoke, :f :get, :key "4", :value nil} {:process 29, :type :ok, :f :append, :key "3", :value "x 29 11 y"} {:process 29, :type :invoke, :f :put, :key "8", :value "x 29 12 y"} {:process 21, :type :ok, :f :get, :key "5", :value "x 43 4 yx 21 0 yx 47 5 yx 26 13 yx 44 2 yx 32 4 yx 29 2 yx 34 2 yx 15 2 yx 25 9 yx 30 6 yx 3 6 yx 31 10 yx 43 8 yx 24 2 yx 10 7 yx 10 9 yx 13 4 yx 29 9 yx 13 5 y"} {:process 21, :type :invoke, :f :get, :key "3", :value nil} {:process 13, :type :ok, :f :append, :key "6", :value "x 13 7 y"} {:process 13, :type :invoke, :f :append, :key "5", :value "x 13 8 y"} {:process 29, :type :ok, :f :put, :key "8", :value "x 29 12 y"} {:process 29, :type :invoke, :f :append, :key "1", :value "x 29 13 y"} {:process 34, :type :ok, :f :get, :key "4", :value "x 31 18 yx 21 5 y"} {:process 34, :type :invoke, :f :put, :key "2", :value "x 34 6 y"} {:process 47, :type :ok, :f :append, :key "1", :value "x 47 20 y"} {:process 47, :type :invoke, :f :append, :key "7", :value "x 47 21 y"} {:process 21, :type :ok, :f :get, :key "3", :value "x 10 8 yx 21 7 yx 29 11 y"} {:process 21, :type :invoke, :f :get, :key "2", :value nil} {:process 2, :type :ok, :f :append, :key "5", :value "x 2 1 y"} {:process 2, :type :invoke, :f :get, :key "7", :value nil} {:process 21, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 yx 40 1 yx 26 17 yx 47 9 yx 49 6 yx 47 13 yx 7 5 yx 39 3 yx 3 5 yx 43 5 yx 7 10 yx 16 1 yx 7 12 yx 41 1 yx 29 6 yx 13 3 yx 13 6 y"} {:process 21, :type :invoke, :f :get, :key "3", :value nil} {:process 21, :type :ok, :f :get, :key "3", :value "x 10 8 yx 21 7 yx 29 11 y"} {:process 21, :type :invoke, :f :get, :key "7", :value nil} {:process 21, :type :ok, :f :get, :key "7", :value "x 19 6 yx 29 7 yx 34 4 y"} {:process 21, :type :invoke, :f :get, :key "9", :value nil} {:process 21, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 yx 44 3 yx 14 6 yx 27 3 yx 24 1 yx 44 4 yx 3 7 yx 9 5 yx 7 11 yx 19 5 yx 11 4 yx 46 5 yx 31 16 yx 21 4 yx 17 7 yx 17 8 yx 29 8 yx 40 3 yx 47 19 y"} {:process 21, :type :invoke, :f :put, :key "1", :value "x 21 8 y"} {:process 0, :type :ok, :f :append, :key "4", :value "x 0 0 y"} {:process 0, :type :invoke, :f :put, :key "1", :value "x 0 1 y"} {:process 2, :type :ok, :f :get, :key "7", :value "x 19 6 yx 29 7 yx 34 4 y"} {:process 2, :type :invoke, :f :get, :key "3", :value nil} {:process 2, :type :ok, :f :get, :key "3", :value "x 10 8 yx 21 7 yx 29 11 y"} {:process 2, :type :invoke, :f :get, :key "8", :value nil} {:process 29, :type :ok, :f :append, :key "1", :value "x 29 13 y"} {:process 29, :type :invoke, :f :append, :key "0", :value "x 29 14 y"} {:process 13, :type :ok, :f :append, :key "5", :value "x 13 8 y"} {:process 13, :type :invoke, :f :append, :key "3", :value "x 13 9 y"} {:process 41, :type :ok, :f :get, :key "5", :value "x 43 4 yx 21 0 yx 47 5 yx 26 13 yx 44 2 yx 32 4 yx 29 2 yx 34 2 yx 15 2 yx 25 9 yx 30 6 yx 3 6 yx 31 10 yx 43 8 yx 24 2 yx 10 7 yx 10 9 yx 13 4 yx 29 9 yx 13 5 y"} {:process 41, :type :invoke, :f :append, :key "2", :value "x 41 4 y"} {:process 48, :type :ok, :f :append, :key "8", :value "x 48 1 y"} {:process 48, :type :invoke, :f :append, :key "1", :value "x 48 2 y"} {:process 0, :type :ok, :f :put, :key "1", :value "x 0 1 y"} {:process 0, :type :invoke, :f :get, :key "8", :value nil} {:process 13, :type :ok, :f :append, :key "3", :value "x 13 9 y"} {:process 13, :type :invoke, :f :get, :key "7", :value nil} {:process 14, :type :ok, :f :append, :key "6", :value "x 14 7 y"} {:process 14, :type :invoke, :f :get, :key "9", :value nil} {:process 13, :type :ok, :f :get, :key "7", :value "x 19 6 yx 29 7 yx 34 4 y"} {:process 13, :type :invoke, :f :get, :key "9", :value nil} {:process 0, :type :ok, :f :get, :key "8", :value "x 29 12 yx 48 1 y"} {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 2 y"} {:process 14, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 yx 44 3 yx 14 6 yx 27 3 yx 24 1 yx 44 4 yx 3 7 yx 9 5 yx 7 11 yx 19 5 yx 11 4 yx 46 5 yx 31 16 yx 21 4 yx 17 7 yx 17 8 yx 29 8 yx 40 3 yx 47 19 y"} {:process 14, :type :invoke, :f :append, :key "8", :value "x 14 8 y"} {:process 29, :type :ok, :f :append, :key "0", :value "x 29 14 y"} {:process 29, :type :invoke, :f :get, :key "7", :value nil} {:process 13, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 yx 44 3 yx 14 6 yx 27 3 yx 24 1 yx 44 4 yx 3 7 yx 9 5 yx 7 11 yx 19 5 yx 11 4 yx 46 5 yx 31 16 yx 21 4 yx 17 7 yx 17 8 yx 29 8 yx 40 3 yx 47 19 y"} {:process 13, :type :invoke, :f :get, :key "6", :value nil} {:process 14, :type :ok, :f :append, :key "8", :value "x 14 8 y"} {:process 14, :type :invoke, :f :get, :key "4", :value nil} {:process 29, :type :ok, :f :get, :key "7", :value "x 19 6 yx 29 7 yx 34 4 y"} {:process 29, :type :invoke, :f :append, :key "7", :value "x 29 15 y"} {:process 7, :type :ok, :f :append, :key "9", :value "x 7 15 y"} {:process 7, :type :invoke, :f :append, :key "0", :value "x 7 16 y"} {:process 45, :type :ok, :f :append, :key "7", :value "x 45 9 y"} {:process 45, :type :invoke, :f :get, :key "7", :value nil} {:process 45, :type :ok, :f :get, :key "7", :value "x 19 6 yx 29 7 yx 34 4 yx 29 15 y"} {:process 45, :type :invoke, :f :append, :key "9", :value "x 45 10 y"} {:process 45, :type :ok, :f :append, :key "9", :value "x 45 10 y"} {:process 45, :type :invoke, :f :append, :key "0", :value "x 45 11 y"} {:process 2, :type :ok, :f :get, :key "8", :value "x 29 12 yx 48 1 yx 14 8 y"} {:process 2, :type :invoke, :f :get, :key "6", :value nil} {:process 2, :type :ok, :f :get, :key "6", :value "x 42 5 yx 26 8 yx 26 11 yx 26 16 yx 36 2 yx 47 8 yx 36 3 yx 35 7 yx 13 1 yx 15 3 yx 37 1 yx 4 7 yx 14 7 yx 9 4 yx 33 3 yx 19 9 yx 13 7 y"} {:process 2, :type :invoke, :f :append, :key "2", :value "x 2 2 y"} {:process 46, :type :ok, :f :append, :key "5", :value "x 46 7 y"} {:process 46, :type :invoke, :f :get, :key "8", :value nil} {:process 45, :type :ok, :f :append, :key "0", :value "x 45 11 y"} {:process 45, :type :invoke, :f :get, :key "2", :value nil} {:process 46, :type :ok, :f :get, :key "8", :value "x 29 12 yx 48 1 yx 14 8 y"} {:process 46, :type :invoke, :f :get, :key "5", :value nil} {:process 22, :type :ok, :f :append, :key "4", :value "x 22 3 y"} {:process 22, :type :invoke, :f :get, :key "4", :value nil} {:process 22, :type :ok, :f :get, :key "4", :value "x 31 18 yx 21 5 y"} {:process 22, :type :invoke, :f :append, :key "7", :value "x 22 4 y"} {:process 20, :type :ok, :f :append, :key "4", :value "x 20 3 y"} {:process 20, :type :invoke, :f :append, :key "9", :value "x 20 4 y"} {:process 27, :type :ok, :f :append, :key "8", :value "x 27 4 y"} {:process 27, :type :invoke, :f :append, :key "2", :value "x 27 5 y"} {:process 4, :type :ok, :f :append, :key "6", :value "x 4 7 y"} {:process 4, :type :invoke, :f :append, :key "5", :value "x 4 8 y"} {:process 3, :type :ok, :f :append, :key "1", :value "x 3 10 y"} {:process 3, :type :invoke, :f :get, :key "9", :value nil} {:process 46, :type :ok, :f :get, :key "5", :value "x 43 4 yx 21 0 yx 47 5 yx 26 13 yx 44 2 yx 32 4 yx 29 2 yx 34 2 yx 15 2 yx 25 9 yx 30 6 yx 3 6 yx 31 10 yx 43 8 yx 24 2 yx 10 7 yx 10 9 yx 13 4 yx 29 9 yx 13 5 yx 13 8 yx 46 7 y"} {:process 46, :type :invoke, :f :get, :key "7", :value nil} {:process 46, :type :ok, :f :get, :key "7", :value "x 19 6 yx 29 7 yx 34 4 yx 29 15 y"} {:process 46, :type :invoke, :f :get, :key "7", :value nil} {:process 20, :type :ok, :f :append, :key "9", :value "x 20 4 y"} {:process 20, :type :invoke, :f :get, :key "7", :value nil} {:process 46, :type :ok, :f :get, :key "7", :value "x 19 6 yx 29 7 yx 34 4 yx 29 15 y"} {:process 46, :type :invoke, :f :put, :key "4", :value "x 46 8 y"} {:process 3, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 yx 44 3 yx 14 6 yx 27 3 yx 24 1 yx 44 4 yx 3 7 yx 9 5 yx 7 11 yx 19 5 yx 11 4 yx 46 5 yx 31 16 yx 21 4 yx 17 7 yx 17 8 yx 29 8 yx 40 3 yx 47 19 yx 7 15 yx 45 10 yx 20 4 y"} {:process 3, :type :invoke, :f :append, :key "1", :value "x 3 11 y"} {:process 27, :type :ok, :f :append, :key "2", :value "x 27 5 y"} {:process 27, :type :invoke, :f :put, :key "4", :value "x 27 6 y"} {:process 22, :type :ok, :f :append, :key "7", :value "x 22 4 y"} {:process 22, :type :invoke, :f :append, :key "1", :value "x 22 5 y"} {:process 20, :type :ok, :f :get, :key "7", :value "x 19 6 yx 29 7 yx 34 4 yx 29 15 yx 22 4 y"} {:process 20, :type :invoke, :f :append, :key "3", :value "x 20 5 y"} {:process 4, :type :ok, :f :append, :key "5", :value "x 4 8 y"} {:process 4, :type :invoke, :f :get, :key "9", :value nil} {:process 46, :type :ok, :f :put, :key "4", :value "x 46 8 y"} {:process 46, :type :invoke, :f :get, :key "4", :value nil} {:process 27, :type :ok, :f :put, :key "4", :value "x 27 6 y"} {:process 27, :type :invoke, :f :get, :key "8", :value nil} {:process 46, :type :ok, :f :get, :key "4", :value "x 27 6 y"} {:process 46, :type :invoke, :f :append, :key "2", :value "x 46 9 y"} {:process 4, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 yx 44 3 yx 14 6 yx 27 3 yx 24 1 yx 44 4 yx 3 7 yx 9 5 yx 7 11 yx 19 5 yx 11 4 yx 46 5 yx 31 16 yx 21 4 yx 17 7 yx 17 8 yx 29 8 yx 40 3 yx 47 19 yx 7 15 yx 45 10 yx 20 4 y"} {:process 4, :type :invoke, :f :get, :key "3", :value nil} {:process 3, :type :ok, :f :append, :key "1", :value "x 3 11 y"} {:process 3, :type :invoke, :f :append, :key "6", :value "x 3 12 y"} {:process 32, :type :ok, :f :append, :key "0", :value "x 32 5 y"} {:process 32, :type :invoke, :f :get, :key "8", :value nil} {:process 4, :type :ok, :f :get, :key "3", :value "x 10 8 yx 21 7 yx 29 11 yx 13 9 y"} {:process 4, :type :invoke, :f :get, :key "4", :value nil} {:process 22, :type :ok, :f :append, :key "1", :value "x 22 5 y"} {:process 22, :type :invoke, :f :append, :key "6", :value "x 22 6 y"} {:process 20, :type :ok, :f :append, :key "3", :value "x 20 5 y"} {:process 20, :type :invoke, :f :append, :key "1", :value "x 20 6 y"} {:process 30, :type :ok, :f :append, :key "5", :value "x 30 6 y"} {:process 30, :type :invoke, :f :append, :key "5", :value "x 30 7 y"} {:process 49, :type :ok, :f :put, :key "1", :value "x 49 7 y"} {:process 49, :type :invoke, :f :append, :key "8", :value "x 49 8 y"} {:process 18, :type :ok, :f :append, :key "0", :value "x 18 2 y"} {:process 18, :type :invoke, :f :get, :key "6", :value nil} {:process 4, :type :ok, :f :get, :key "4", :value "x 27 6 y"} {:process 4, :type :invoke, :f :append, :key "3", :value "x 4 9 y"} {:process 32, :type :ok, :f :get, :key "8", :value "x 29 12 yx 48 1 yx 14 8 y"} {:process 32, :type :invoke, :f :get, :key "8", :value nil} {:process 3, :type :ok, :f :append, :key "6", :value "x 3 12 y"} {:process 3, :type :invoke, :f :append, :key "4", :value "x 3 13 y"} {:process 22, :type :ok, :f :append, :key "6", :value "x 22 6 y"} {:process 22, :type :invoke, :f :append, :key "2", :value "x 22 7 y"} {:process 20, :type :ok, :f :append, :key "1", :value "x 20 6 y"} {:process 20, :type :invoke, :f :get, :key "1", :value nil} {:process 32, :type :ok, :f :get, :key "8", :value "x 29 12 yx 48 1 yx 14 8 y"} {:process 32, :type :invoke, :f :get, :key "9", :value nil} {:process 49, :type :ok, :f :append, :key "8", :value "x 49 8 y"} {:process 49, :type :invoke, :f :get, :key "8", :value nil} {:process 22, :type :ok, :f :append, :key "2", :value "x 22 7 y"} {:process 22, :type :invoke, :f :append, :key "4", :value "x 22 8 y"} {:process 45, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 yx 40 1 yx 26 17 yx 47 9 yx 49 6 yx 47 13 yx 7 5 yx 39 3 yx 3 5 yx 43 5 yx 7 10 yx 16 1 yx 7 12 yx 41 1 yx 29 6 yx 13 3 yx 13 6 yx 27 5 y"} {:process 45, :type :invoke, :f :append, :key "2", :value "x 45 12 y"} {:process 3, :type :ok, :f :append, :key "4", :value "x 3 13 y"} {:process 3, :type :invoke, :f :append, :key "1", :value "x 3 14 y"} {:process 32, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 yx 44 3 yx 14 6 yx 27 3 yx 24 1 yx 44 4 yx 3 7 yx 9 5 yx 7 11 yx 19 5 yx 11 4 yx 46 5 yx 31 16 yx 21 4 yx 17 7 yx 17 8 yx 29 8 yx 40 3 yx 47 19 yx 7 15 yx 45 10 yx 20 4 y"} {:process 32, :type :invoke, :f :append, :key "0", :value "x 32 6 y"} {:process 14, :type :ok, :f :get, :key "4", :value "x 27 6 y"} {:process 14, :type :invoke, :f :get, :key "2", :value nil} {:process 5, :type :ok, :f :append, :key "8", :value "x 5 1 y"} {:process 5, :type :invoke, :f :append, :key "0", :value "x 5 2 y"} {:process 22, :type :ok, :f :append, :key "4", :value "x 22 8 y"} {:process 22, :type :invoke, :f :get, :key "8", :value nil} {:process 22, :type :ok, :f :get, :key "8", :value "x 29 12 yx 48 1 yx 14 8 yx 49 8 y"} {:process 22, :type :invoke, :f :get, :key "8", :value nil} {:process 22, :type :ok, :f :get, :key "8", :value "x 29 12 yx 48 1 yx 14 8 yx 49 8 y"} {:process 22, :type :invoke, :f :append, :key "3", :value "x 22 9 y"} {:process 49, :type :ok, :f :get, :key "8", :value "x 29 12 yx 48 1 yx 14 8 yx 49 8 y"} {:process 49, :type :invoke, :f :append, :key "2", :value "x 49 9 y"} {:process 32, :type :ok, :f :append, :key "0", :value "x 32 6 y"} {:process 32, :type :invoke, :f :append, :key "8", :value "x 32 7 y"} {:process 5, :type :ok, :f :append, :key "0", :value "x 5 2 y"} {:process 5, :type :invoke, :f :append, :key "7", :value "x 5 3 y"} {:process 15, :type :ok, :f :append, :key "6", :value "x 15 3 y"} {:process 15, :type :invoke, :f :append, :key "9", :value "x 15 4 y"} {:process 3, :type :ok, :f :append, :key "1", :value "x 3 14 y"} {:process 3, :type :invoke, :f :get, :key "5", :value nil} {:process 3, :type :ok, :f :get, :key "5", :value "x 43 4 yx 21 0 yx 47 5 yx 26 13 yx 44 2 yx 32 4 yx 29 2 yx 34 2 yx 15 2 yx 25 9 yx 30 6 yx 3 6 yx 31 10 yx 43 8 yx 24 2 yx 10 7 yx 10 9 yx 13 4 yx 29 9 yx 13 5 yx 13 8 yx 46 7 yx 4 8 y"} {:process 3, :type :invoke, :f :get, :key "7", :value nil} {:process 3, :type :ok, :f :get, :key "7", :value "x 19 6 yx 29 7 yx 34 4 yx 29 15 yx 22 4 y"} {:process 3, :type :invoke, :f :get, :key "6", :value nil} {:process 14, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 yx 40 1 yx 26 17 yx 47 9 yx 49 6 yx 47 13 yx 7 5 yx 39 3 yx 3 5 yx 43 5 yx 7 10 yx 16 1 yx 7 12 yx 41 1 yx 29 6 yx 13 3 yx 13 6 yx 27 5 yx 22 7 y"} {:process 14, :type :invoke, :f :get, :key "7", :value nil} {:process 49, :type :ok, :f :append, :key "2", :value "x 49 9 y"} {:process 49, :type :invoke, :f :get, :key "6", :value nil} {:process 15, :type :ok, :f :append, :key "9", :value "x 15 4 y"} {:process 15, :type :invoke, :f :get, :key "9", :value nil} {:process 49, :type :ok, :f :get, :key "6", :value "x 42 5 yx 26 8 yx 26 11 yx 26 16 yx 36 2 yx 47 8 yx 36 3 yx 35 7 yx 13 1 yx 15 3 yx 37 1 yx 4 7 yx 14 7 yx 9 4 yx 33 3 yx 19 9 yx 13 7 yx 3 12 yx 22 6 y"} {:process 49, :type :invoke, :f :put, :key "9", :value "x 49 10 y"} {:process 32, :type :ok, :f :append, :key "8", :value "x 32 7 y"} {:process 32, :type :invoke, :f :append, :key "9", :value "x 32 8 y"} {:process 22, :type :ok, :f :append, :key "3", :value "x 22 9 y"} {:process 22, :type :invoke, :f :get, :key "9", :value nil} {:process 3, :type :ok, :f :get, :key "6", :value "x 42 5 yx 26 8 yx 26 11 yx 26 16 yx 36 2 yx 47 8 yx 36 3 yx 35 7 yx 13 1 yx 15 3 yx 37 1 yx 4 7 yx 14 7 yx 9 4 yx 33 3 yx 19 9 yx 13 7 yx 3 12 yx 22 6 y"} {:process 3, :type :invoke, :f :get, :key "0", :value nil} {:process 27, :type :ok, :f :get, :key "8", :value "x 29 12 yx 48 1 yx 14 8 yx 49 8 y"} {:process 27, :type :invoke, :f :get, :key "7", :value nil} {:process 3, :type :ok, :f :get, :key "0", :value "x 10 3 yx 45 7 yx 32 5 yx 49 5 yx 14 5 yx 21 3 yx 28 1 yx 1 1 yx 3 9 yx 40 2 yx 33 1 yx 7 14 yx 38 4 yx 24 3 yx 31 17 yx 19 7 yx 21 6 yx 34 5 yx 10 11 yx 29 14 yx 0 2 yx 7 16 yx 45 11 yx 18 2 yx 32 6 yx 5 2 y"} {:process 3, :type :invoke, :f :put, :key "8", :value "x 3 15 y"} {:process 27, :type :ok, :f :get, :key "7", :value "x 19 6 yx 29 7 yx 34 4 yx 29 15 yx 22 4 y"} {:process 27, :type :invoke, :f :get, :key "5", :value nil} {:process 27, :type :ok, :f :get, :key "5", :value "x 43 4 yx 21 0 yx 47 5 yx 26 13 yx 44 2 yx 32 4 yx 29 2 yx 34 2 yx 15 2 yx 25 9 yx 30 6 yx 3 6 yx 31 10 yx 43 8 yx 24 2 yx 10 7 yx 10 9 yx 13 4 yx 29 9 yx 13 5 yx 13 8 yx 46 7 yx 4 8 y"} {:process 27, :type :invoke, :f :append, :key "8", :value "x 27 7 y"} {:process 14, :type :ok, :f :get, :key "7", :value "x 19 6 yx 29 7 yx 34 4 yx 29 15 yx 22 4 y"} {:process 14, :type :invoke, :f :append, :key "0", :value "x 14 9 y"} {:process 8, :type :ok, :f :append, :key "0", :value "x 8 6 y"} {:process 8, :type :invoke, :f :append, :key "6", :value "x 8 7 y"} {:process 15, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 yx 44 3 yx 14 6 yx 27 3 yx 24 1 yx 44 4 yx 3 7 yx 9 5 yx 7 11 yx 19 5 yx 11 4 yx 46 5 yx 31 16 yx 21 4 yx 17 7 yx 17 8 yx 29 8 yx 40 3 yx 47 19 yx 7 15 yx 45 10 yx 20 4 yx 15 4 y"} {:process 15, :type :invoke, :f :append, :key "0", :value "x 15 5 y"} {:process 5, :type :ok, :f :append, :key "7", :value "x 5 3 y"} {:process 5, :type :invoke, :f :append, :key "6", :value "x 5 4 y"} {:process 3, :type :ok, :f :put, :key "8", :value "x 3 15 y"} {:process 3, :type :invoke, :f :get, :key "9", :value nil} {:process 8, :type :ok, :f :append, :key "6", :value "x 8 7 y"} {:process 8, :type :invoke, :f :append, :key "9", :value "x 8 8 y"} {:process 32, :type :ok, :f :append, :key "9", :value "x 32 8 y"} {:process 32, :type :invoke, :f :put, :key "8", :value "x 32 9 y"} {:process 15, :type :ok, :f :append, :key "0", :value "x 15 5 y"} {:process 15, :type :invoke, :f :append, :key "5", :value "x 15 6 y"} {:process 22, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 yx 44 3 yx 14 6 yx 27 3 yx 24 1 yx 44 4 yx 3 7 yx 9 5 yx 7 11 yx 19 5 yx 11 4 yx 46 5 yx 31 16 yx 21 4 yx 17 7 yx 17 8 yx 29 8 yx 40 3 yx 47 19 yx 7 15 yx 45 10 yx 20 4 yx 15 4 yx 32 8 y"} {:process 22, :type :invoke, :f :get, :key "6", :value nil} {:process 3, :type :ok, :f :get, :key "9", :value "x 47 6 yx 6 5 yx 44 3 yx 14 6 yx 27 3 yx 24 1 yx 44 4 yx 3 7 yx 9 5 yx 7 11 yx 19 5 yx 11 4 yx 46 5 yx 31 16 yx 21 4 yx 17 7 yx 17 8 yx 29 8 yx 40 3 yx 47 19 yx 7 15 yx 45 10 yx 20 4 yx 15 4 yx 32 8 y"} {:process 3, :type :invoke, :f :put, :key "0", :value "x 3 16 y"} {:process 32, :type :ok, :f :put, :key "8", :value "x 32 9 y"} {:process 49, :type :ok, :f :put, :key "9", :value "x 49 10 y"} {:process 49, :type :invoke, :f :get, :key "2", :value nil} {:process 32, :type :invoke, :f :append, :key "3", :value "x 32 10 y"} {:process 49, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 yx 40 1 yx 26 17 yx 47 9 yx 49 6 yx 47 13 yx 7 5 yx 39 3 yx 3 5 yx 43 5 yx 7 10 yx 16 1 yx 7 12 yx 41 1 yx 29 6 yx 13 3 yx 13 6 yx 27 5 yx 22 7 yx 49 9 y"} {:process 49, :type :invoke, :f :append, :key "1", :value "x 49 11 y"} {:process 15, :type :ok, :f :append, :key "5", :value "x 15 6 y"} {:process 15, :type :invoke, :f :append, :key "2", :value "x 15 7 y"} {:process 22, :type :ok, :f :get, :key "6", :value "x 42 5 yx 26 8 yx 26 11 yx 26 16 yx 36 2 yx 47 8 yx 36 3 yx 35 7 yx 13 1 yx 15 3 yx 37 1 yx 4 7 yx 14 7 yx 9 4 yx 33 3 yx 19 9 yx 13 7 yx 3 12 yx 22 6 yx 8 7 y"} {:process 22, :type :invoke, :f :get, :key "2", :value nil} {:process 5, :type :ok, :f :append, :key "6", :value "x 5 4 y"} {:process 5, :type :invoke, :f :get, :key "0", :value nil} {:process 8, :type :ok, :f :append, :key "9", :value "x 8 8 y"} {:process 8, :type :invoke, :f :get, :key "0", :value nil} {:process 3, :type :ok, :f :put, :key "0", :value "x 3 16 y"} {:process 3, :type :invoke, :f :append, :key "6", :value "x 3 17 y"} {:process 15, :type :ok, :f :append, :key "2", :value "x 15 7 y"} {:process 15, :type :invoke, :f :append, :key "9", :value "x 15 8 y"} {:process 49, :type :ok, :f :append, :key "1", :value "x 49 11 y"} {:process 49, :type :invoke, :f :append, :key "5", :value "x 49 12 y"} {:process 6, :type :ok, :f :append, :key "9", :value "x 6 6 y"} {:process 6, :type :invoke, :f :get, :key "9", :value nil} {:process 8, :type :ok, :f :get, :key "0", :value "x 3 16 y"} {:process 8, :type :invoke, :f :get, :key "4", :value nil} {:process 1, :type :ok, :f :append, :key "0", :value "x 1 1 y"} {:process 1, :type :invoke, :f :get, :key "3", :value nil} {:process 49, :type :ok, :f :append, :key "5", :value "x 49 12 y"} {:process 49, :type :invoke, :f :get, :key "1", :value nil} {:process 8, :type :ok, :f :get, :key "4", :value "x 27 6 yx 3 13 yx 22 8 y"} {:process 8, :type :invoke, :f :get, :key "9", :value nil} {:process 3, :type :ok, :f :append, :key "6", :value "x 3 17 y"} {:process 33, :type :ok, :f :append, :key "6", :value "x 33 3 y"} {:process 33, :type :invoke, :f :get, :key "3", :value nil} {:process 3, :type :invoke, :f :append, :key "2", :value "x 3 18 y"} {:process 15, :type :ok, :f :append, :key "9", :value "x 15 8 y"} {:process 15, :type :invoke, :f :get, :key "9", :value nil} {:process 15, :type :ok, :f :get, :key "9", :value "x 49 10 yx 8 8 yx 6 6 yx 15 8 y"} {:process 15, :type :invoke, :f :append, :key "9", :value "x 15 9 y"} {:process 49, :type :ok, :f :get, :key "1", :value "x 0 1 yx 3 11 yx 22 5 yx 20 6 yx 3 14 yx 49 11 y"} {:process 49, :type :invoke, :f :append, :key "3", :value "x 49 13 y"} {:process 28, :type :ok, :f :append, :key "4", :value "x 28 2 y"} {:process 28, :type :invoke, :f :append, :key "7", :value "x 28 3 y"} {:process 8, :type :ok, :f :get, :key "9", :value "x 49 10 yx 8 8 yx 6 6 yx 15 8 y"} {:process 8, :type :invoke, :f :append, :key "8", :value "x 8 9 y"} {:process 3, :type :ok, :f :append, :key "2", :value "x 3 18 y"} {:process 3, :type :invoke, :f :get, :key "2", :value nil} {:process 33, :type :ok, :f :get, :key "3", :value "x 10 8 yx 21 7 yx 29 11 yx 13 9 yx 20 5 yx 22 9 y"} {:process 33, :type :invoke, :f :get, :key "5", :value nil} {:process 3, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 yx 40 1 yx 26 17 yx 47 9 yx 49 6 yx 47 13 yx 7 5 yx 39 3 yx 3 5 yx 43 5 yx 7 10 yx 16 1 yx 7 12 yx 41 1 yx 29 6 yx 13 3 yx 13 6 yx 27 5 yx 22 7 yx 49 9 yx 15 7 yx 3 18 y"} {:process 3, :type :invoke, :f :append, :key "9", :value "x 3 19 y"} {:process 33, :type :ok, :f :get, :key "5", :value "x 43 4 yx 21 0 yx 47 5 yx 26 13 yx 44 2 yx 32 4 yx 29 2 yx 34 2 yx 15 2 yx 25 9 yx 30 6 yx 3 6 yx 31 10 yx 43 8 yx 24 2 yx 10 7 yx 10 9 yx 13 4 yx 29 9 yx 13 5 yx 13 8 yx 46 7 yx 4 8 yx 15 6 yx 49 12 y"} {:process 33, :type :invoke, :f :append, :key "8", :value "x 33 4 y"} {:process 16, :type :ok, :f :append, :key "3", :value "x 16 3 y"} {:process 16, :type :invoke, :f :append, :key "8", :value "x 16 4 y"} {:process 28, :type :ok, :f :append, :key "7", :value "x 28 3 y"} {:process 28, :type :invoke, :f :append, :key "0", :value "x 28 4 y"} {:process 15, :type :ok, :f :append, :key "9", :value "x 15 9 y"} {:process 15, :type :invoke, :f :append, :key "8", :value "x 15 10 y"} {:process 33, :type :ok, :f :append, :key "8", :value "x 33 4 y"} {:process 33, :type :invoke, :f :get, :key "6", :value nil} {:process 3, :type :ok, :f :append, :key "9", :value "x 3 19 y"} {:process 3, :type :invoke, :f :get, :key "8", :value nil} {:process 8, :type :ok, :f :append, :key "8", :value "x 8 9 y"} {:process 8, :type :invoke, :f :get, :key "0", :value nil} {:process 22, :type :ok, :f :get, :key "2", :value "x 30 1 yx 8 1 yx 30 5 yx 9 0 yx 9 1 yx 31 8 yx 42 0 yx 38 0 yx 26 3 yx 14 1 yx 19 2 yx 6 0 yx 6 1 yx 32 2 yx 32 3 yx 49 3 yx 40 1 yx 26 17 yx 47 9 yx 49 6 yx 47 13 yx 7 5 yx 39 3 yx 3 5 yx 43 5 yx 7 10 yx 16 1 yx 7 12 yx 41 1 yx 29 6 yx 13 3 yx 13 6 yx 27 5 yx 22 7 yx 49 9 yx 15 7 yx 3 18 y"} {:process 22, :type :invoke, :f :get, :key "5", :value nil} {:process 33, :type :ok, :f :get, :key "6", :value "x 42 5 yx 26 8 yx 26 11 yx 26 16 yx 36 2 yx 47 8 yx 36 3 yx 35 7 yx 13 1 yx 15 3 yx 37 1 yx 4 7 yx 14 7 yx 9 4 yx 33 3 yx 19 9 yx 13 7 yx 3 12 yx 22 6 yx 8 7 yx 5 4 yx 3 17 y"} {:process 33, :type :invoke, :f :append, :key "4", :value "x 33 5 y"} {:process 22, :type :ok, :f :get, :key "5", :value "x 43 4 yx 21 0 yx 47 5 yx 26 13 yx 44 2 yx 32 4 yx 29 2 yx 34 2 yx 15 2 yx 25 9 yx 30 6 yx 3 6 yx 31 10 yx 43 8 yx 24 2 yx 10 7 yx 10 9 yx 13 4 yx 29 9 yx 13 5 yx 13 8 yx 46 7 yx 4 8 yx 15 6 yx 49 12 y"} {:process 22, :type :invoke, :f :get, :key "7", :value nil} {:process 16, :type :ok, :f :append, :key "8", :value "x 16 4 y"} {:process 16, :type :invoke, :f :get, :key "0", :value nil} {:process 15, :type :ok, :f :append, :key "8", :value "x 15 10 y"} {:process 15, :type :invoke, :f :append, :key "6", :value "x 15 11 y"} {:process 28, :type :ok, :f :append, :key "0", :value "x 28 4 y"} {:process 28, :type :invoke, :f :get, :key "6", :value nil} {:process 3, :type :ok, :f :get, :key "8", :value "x 32 9 yx 33 4 yx 8 9 yx 16 4 yx 15 10 y"} {:process 3, :type :invoke, :f :append, :key "5", :value "x 3 20 y"} {:process 8, :type :ok, :f :get, :key "0", :value "x 3 16 yx 28 4 y"} {:process 8, :type :invoke, :f :append, :key "9", :value "x 8 10 y"} {:process 5, :type :ok, :f :get, :key "0", :value "x 3 16 y"} {:process 5, :type :invoke, :f :append, :key "9", :value "x 5 5 y"} {:process 28, :type :ok, :f :get, :key "6", :value "x 42 5 yx 26 8 yx 26 11 yx 26 16 yx 36 2 yx 47 8 yx 36 3 yx 35 7 yx 13 1 yx 15 3 yx 37 1 yx 4 7 yx 14 7 yx 9 4 yx 33 3 yx 19 9 yx 13 7 yx 3 12 yx 22 6 yx 8 7 yx 5 4 yx 3 17 y"} {:process 28, :type :invoke, :f :append, :key "5", :value "x 28 5 y"} {:process 33, :type :ok, :f :append, :key "4", :value "x 33 5 y"} {:process 33, :type :invoke, :f :append, :key "8", :value "x 33 6 y"} {:process 15, :type :ok, :f :append, :key "6", :value "x 15 11 y"} {:process 15, :type :invoke, :f :append, :key "4", :value "x 15 12 y"} {:process 16, :type :ok, :f :get, :key "0", :value "x 3 16 yx 28 4 y"} {:process 16, :type :invoke, :f :get, :key "0", :value nil} {:process 28, :type :ok, :f :append, :key "5", :value "x 28 5 y"} {:process 28, :type :invoke, :f :append, :key "5", :value "x 28 6 y"} {:process 8, :type :ok, :f :append, :key "9", :value "x 8 10 y"} {:process 8, :type :invoke, :f :get, :key "4", :value nil} {:process 3, :type :ok, :f :append, :key "5", :value "x 3 20 y"} {:process 3, :type :invoke, :f :get, :key "7", :value nil} {:process 15, :type :ok, :f :append, :key "4", :value "x 15 12 y"} {:process 15, :type :invoke, :f :get, :key "1", :value nil} {:process 16, :type :ok, :f :get, :key "0", :value "x 3 16 yx 28 4 y"} {:process 16, :type :invoke, :f :get, :key "9", :value nil} {:process 13, :type :ok, :f :get, :key "6", :value "x 42 5 yx 26 8 yx 26 11 yx 26 16 yx 36 2 yx 47 8 yx 36 3 yx 35 7 yx 13 1 yx 15 3 yx 37 1 yx 4 7 yx 14 7 yx 9 4 yx 33 3 yx 19 9 yx 13 7 yx 3 12 yx 22 6 yx 8 7 yx 5 4 yx 3 17 y"} {:process 13, :type :invoke, :f :append, :key "0", :value "x 13 10 y"} {:process 8, :type :ok, :f :get, :key "4", :value "x 27 6 yx 3 13 yx 22 8 yx 28 2 yx 33 5 yx 15 12 y"} {:process 8, :type :invoke, :f :append, :key "4", :value "x 8 11 y"} {:process 3, :type :ok, :f :get, :key "7", :value "x 19 6 yx 29 7 yx 34 4 yx 29 15 yx 22 4 yx 5 3 yx 28 3 y"} {:process 3, :type :invoke, :f :append, :key "1", :value "x 3 21 y"} {:process 28, :type :ok, :f :append, :key "5", :value "x 28 6 y"} {:process 28, :type :invoke, :f :append, :key "7", :value "x 28 7 y"} {:process 6, :type :ok, :f :get, :key "9", :value "x 49 10 yx 8 8 yx 6 6 yx 15 8 yx 15 9 yx 3 19 yx 8 10 y"} {:process 6, :type :invoke, :f :get, :key "6", :value nil} {:process 1, :type :ok, :f :get, :key "3", :value "x 10 8 yx 21 7 yx 29 11 yx 13 9 yx 20 5 yx 22 9 yx 16 3 yx 11 5 y"} {:process 1, :type :invoke, :f :get, :key "0", :value nil} {:process 1, :type :ok, :f :get, :key "0", :value "x 3 16 yx 28 4 y"} {:process 1, :type :invoke, :f :append, :key "4", :value "x 1 2 y"} {:process 15, :type :ok, :f :get, :key "1", :value "x 0 1 yx 3 11 yx 22 5 yx 20 6 yx 3 14 yx 49 11 y"} {:process 15, :type :invoke, :f :append, :key "1", :value "x 15 13 y"} {:process 22, :type :ok, :f :get, :key "7", :value ""} {:process 16, :type :ok, :f :get, :key "9", :value ""} {:process 18, :type :ok, :f :get, :key "6", :value ""} {:process 6, :type :ok, :f :get, :key "6", :value ""} {:process 20, :type :ok, :f :get, :key "1", :value ""} {:process 17, :type :ok, :f :append, :key "9", :value "x 17 8 y"} {:process 38, :type :ok, :f :append, :key "3", :value "x 38 5 y"} {:process 41, :type :ok, :f :append, :key "2", :value "x 41 4 y"} {:process 19, :type :ok, :f :append, :key "9", :value "x 19 10 y"} {:process 24, :type :ok, :f :append, :key "0", :value "x 24 3 y"} {:process 12, :type :ok, :f :append, :key "9", :value "x 12 1 y"} {:process 7, :type :ok, :f :append, :key "0", :value "x 7 16 y"} {:process 29, :type :ok, :f :append, :key "7", :value "x 29 15 y"} {:process 47, :type :ok, :f :append, :key "7", :value "x 47 21 y"} {:process 34, :type :ok, :f :put, :key "2", :value "x 34 6 y"} {:process 40, :type :ok, :f :append, :key "0", :value "x 40 4 y"} {:process 48, :type :ok, :f :append, :key "1", :value "x 48 2 y"} {:process 2, :type :ok, :f :append, :key "2", :value "x 2 2 y"} {:process 39, :type :ok, :f :append, :key "2", :value "x 39 3 y"} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 2 y"} {:process 13, :type :ok, :f :append, :key "0", :value "x 13 10 y"} {:process 45, :type :ok, :f :append, :key "2", :value "x 45 12 y"} {:process 23, :type :ok, :f :append, :key "3", :value "x 23 5 y"} {:process 27, :type :ok, :f :append, :key "8", :value "x 27 7 y"} {:process 46, :type :ok, :f :append, :key "2", :value "x 46 9 y"} {:process 4, :type :ok, :f :append, :key "3", :value "x 4 9 y"} {:process 30, :type :ok, :f :append, :key "5", :value "x 30 7 y"} {:process 36, :type :ok, :f :append, :key "1", :value "x 36 4 y"} {:process 44, :type :ok, :f :append, :key "9", :value "x 44 4 y"} {:process 5, :type :ok, :f :append, :key "9", :value "x 5 5 y"} {:process 49, :type :ok, :f :append, :key "3", :value "x 49 13 y"} {:process 1, :type :ok, :f :append, :key "4", :value "x 1 2 y"} {:process 33, :type :ok, :f :append, :key "8", :value "x 33 6 y"} {:process 11, :type :ok, :f :append, :key "3", :value "x 11 5 y"} {:process 8, :type :ok, :f :append, :key "4", :value "x 8 11 y"} {:process 37, :type :ok, :f :append, :key "7", :value "x 37 4 y"} {:process 35, :type :ok, :f :append, :key "1", :value "x 35 9 y"} {:process 3, :type :ok, :f :append, :key "1", :value "x 3 21 y"} {:process 28, :type :ok, :f :append, :key "7", :value "x 28 7 y"} {:process 9, :type :ok, :f :put, :key "4", :value "x 9 7 y"} {:process 15, :type :ok, :f :append, :key "1", :value "x 15 13 y"} {:process 31, :type :ok, :f :put, :key "4", :value "x 31 18 y"} {:process 21, :type :ok, :f :put, :key "1", :value "x 21 8 y"} {:process 10, :type :ok, :f :append, :key "1", :value "x 10 12 y"} {:process 14, :type :ok, :f :append, :key "0", :value "x 14 9 y"} {:process 42, :type :ok, :f :put, :key "6", :value "x 42 5 y"} {:process 32, :type :ok, :f :append, :key "3", :value "x 32 10 y"} {:process 26, :type :ok, :f :append, :key "4", :value "x 26 18 y"} {:process 25, :type :ok, :f :append, :key "5", :value "x 25 9 y"} {:process 43, :type :ok, :f :append, :key "1", :value "x 43 9 y"} ================================================ FILE: courses/dss/linearizability/test_data/c50-ok.txt ================================================ {:process 6, :type :invoke, :f :append, :key "0", :value "x 6 0 y"} {:process 18, :type :invoke, :f :append, :key "1", :value "x 18 0 y"} {:process 7, :type :invoke, :f :append, :key "0", :value "x 7 0 y"} {:process 8, :type :invoke, :f :get, :key "9", :value nil} {:process 9, :type :invoke, :f :append, :key "9", :value "x 9 0 y"} {:process 10, :type :invoke, :f :append, :key "9", :value "x 10 0 y"} {:process 11, :type :invoke, :f :get, :key "7", :value nil} {:process 12, :type :invoke, :f :append, :key "5", :value "x 12 0 y"} {:process 13, :type :invoke, :f :get, :key "4", :value nil} {:process 14, :type :invoke, :f :get, :key "6", :value nil} {:process 15, :type :invoke, :f :append, :key "2", :value "x 15 0 y"} {:process 2, :type :invoke, :f :append, :key "4", :value "x 2 0 y"} {:process 16, :type :invoke, :f :get, :key "4", :value nil} {:process 17, :type :invoke, :f :get, :key "8", :value nil} {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 0 y"} {:process 32, :type :invoke, :f :append, :key "6", :value "x 32 0 y"} {:process 1, :type :invoke, :f :get, :key "6", :value nil} {:process 19, :type :invoke, :f :append, :key "6", :value "x 19 0 y"} {:process 4, :type :invoke, :f :append, :key "4", :value "x 4 0 y"} {:process 20, :type :invoke, :f :get, :key "2", :value nil} {:process 21, :type :invoke, :f :append, :key "1", :value "x 21 0 y"} {:process 3, :type :invoke, :f :put, :key "7", :value "x 3 0 y"} {:process 22, :type :invoke, :f :append, :key "1", :value "x 22 0 y"} {:process 23, :type :invoke, :f :get, :key "2", :value nil} {:process 39, :type :invoke, :f :append, :key "2", :value "x 39 0 y"} {:process 24, :type :invoke, :f :get, :key "3", :value nil} {:process 33, :type :invoke, :f :get, :key "9", :value nil} {:process 25, :type :invoke, :f :append, :key "7", :value "x 25 0 y"} {:process 34, :type :invoke, :f :get, :key "4", :value nil} {:process 26, :type :invoke, :f :put, :key "7", :value "x 26 0 y"} {:process 35, :type :invoke, :f :append, :key "9", :value "x 35 0 y"} {:process 36, :type :invoke, :f :get, :key "5", :value nil} {:process 37, :type :invoke, :f :get, :key "1", :value nil} {:process 38, :type :invoke, :f :get, :key "5", :value nil} {:process 27, :type :invoke, :f :append, :key "9", :value "x 27 0 y"} {:process 42, :type :invoke, :f :append, :key "0", :value "x 42 0 y"} {:process 28, :type :invoke, :f :get, :key "3", :value nil} {:process 40, :type :invoke, :f :append, :key "5", :value "x 40 0 y"} {:process 29, :type :invoke, :f :put, :key "5", :value "x 29 0 y"} {:process 41, :type :invoke, :f :append, :key "0", :value "x 41 0 y"} {:process 30, :type :invoke, :f :get, :key "1", :value nil} {:process 44, :type :invoke, :f :append, :key "9", :value "x 44 0 y"} {:process 43, :type :invoke, :f :append, :key "3", :value "x 43 0 y"} {:process 31, :type :invoke, :f :get, :key "1", :value nil} {:process 5, :type :invoke, :f :append, :key "7", :value "x 5 0 y"} {:process 46, :type :invoke, :f :append, :key "9", :value "x 46 0 y"} {:process 49, :type :invoke, :f :get, :key "4", :value nil} {:process 45, :type :invoke, :f :put, :key "2", :value "x 45 0 y"} {:process 48, :type :invoke, :f :get, :key "0", :value nil} {:process 47, :type :invoke, :f :get, :key "5", :value nil} {:process 6, :type :ok, :f :append, :key "0", :value "x 6 0 y"} {:process 6, :type :invoke, :f :get, :key "5", :value nil} {:process 39, :type :ok, :f :append, :key "2", :value "x 39 0 y"} {:process 39, :type :invoke, :f :get, :key "1", :value nil} {:process 11, :type :ok, :f :get, :key "7", :value ""} {:process 11, :type :invoke, :f :get, :key "2", :value nil} {:process 21, :type :ok, :f :append, :key "1", :value "x 21 0 y"} {:process 21, :type :invoke, :f :append, :key "4", :value "x 21 1 y"} {:process 11, :type :ok, :f :get, :key "2", :value "x 39 0 y"} {:process 11, :type :invoke, :f :append, :key "8", :value "x 11 0 y"} {:process 21, :type :ok, :f :append, :key "4", :value "x 21 1 y"} {:process 21, :type :invoke, :f :append, :key "0", :value "x 21 2 y"} {:process 21, :type :ok, :f :append, :key "0", :value "x 21 2 y"} {:process 21, :type :invoke, :f :get, :key "5", :value nil} {:process 21, :type :ok, :f :get, :key "5", :value ""} {:process 21, :type :invoke, :f :get, :key "7", :value nil} {:process 47, :type :ok, :f :get, :key "5", :value ""} {:process 47, :type :invoke, :f :append, :key "5", :value "x 47 0 y"} {:process 21, :type :ok, :f :get, :key "7", :value ""} {:process 21, :type :invoke, :f :append, :key "3", :value "x 21 3 y"} {:process 47, :type :ok, :f :append, :key "5", :value "x 47 0 y"} {:process 47, :type :invoke, :f :get, :key "6", :value nil} {:process 21, :type :ok, :f :append, :key "3", :value "x 21 3 y"} {:process 21, :type :invoke, :f :append, :key "0", :value "x 21 4 y"} {:process 21, :type :ok, :f :append, :key "0", :value "x 21 4 y"} {:process 21, :type :invoke, :f :append, :key "4", :value "x 21 5 y"} {:process 3, :type :ok, :f :put, :key "7", :value "x 3 0 y"} {:process 3, :type :invoke, :f :get, :key "6", :value nil} {:process 21, :type :ok, :f :append, :key "4", :value "x 21 5 y"} {:process 21, :type :invoke, :f :append, :key "9", :value "x 21 6 y"} {:process 30, :type :ok, :f :get, :key "1", :value "x 21 0 y"} {:process 30, :type :invoke, :f :append, :key "2", :value "x 30 0 y"} {:process 3, :type :ok, :f :get, :key "6", :value ""} {:process 3, :type :invoke, :f :append, :key "8", :value "x 3 1 y"} {:process 21, :type :ok, :f :append, :key "9", :value "x 21 6 y"} {:process 21, :type :invoke, :f :append, :key "8", :value "x 21 7 y"} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 0 y"} {:process 0, :type :invoke, :f :get, :key "6", :value nil} {:process 21, :type :ok, :f :append, :key "8", :value "x 21 7 y"} {:process 21, :type :invoke, :f :get, :key "5", :value nil} {:process 21, :type :ok, :f :get, :key "5", :value "x 47 0 y"} {:process 21, :type :invoke, :f :append, :key "8", :value "x 21 8 y"} {:process 8, :type :ok, :f :get, :key "9", :value "x 46 0 yx 21 6 yx 44 0 y"} {:process 8, :type :invoke, :f :get, :key "0", :value nil} {:process 8, :type :ok, :f :get, :key "0", :value "x 6 0 yx 21 2 yx 21 4 yx 0 0 y"} {:process 8, :type :invoke, :f :put, :key "3", :value "x 8 0 y"} {:process 21, :type :ok, :f :append, :key "8", :value "x 21 8 y"} {:process 21, :type :invoke, :f :get, :key "3", :value nil} {:process 13, :type :ok, :f :get, :key "4", :value "x 21 1 yx 21 5 y"} {:process 13, :type :invoke, :f :append, :key "0", :value "x 13 0 y"} {:process 8, :type :ok, :f :put, :key "3", :value "x 8 0 y"} {:process 8, :type :invoke, :f :get, :key "2", :value nil} {:process 21, :type :ok, :f :get, :key "3", :value "x 8 0 y"} {:process 21, :type :invoke, :f :append, :key "3", :value "x 21 9 y"} {:process 5, :type :ok, :f :append, :key "7", :value "x 5 0 y"} {:process 5, :type :invoke, :f :get, :key "2", :value nil} {:process 27, :type :ok, :f :append, :key "9", :value "x 27 0 y"} {:process 27, :type :invoke, :f :get, :key "9", :value nil} {:process 24, :type :ok, :f :get, :key "3", :value "x 8 0 y"} {:process 24, :type :invoke, :f :get, :key "4", :value nil} {:process 13, :type :ok, :f :append, :key "0", :value "x 13 0 y"} {:process 13, :type :invoke, :f :get, :key "5", :value nil} {:process 21, :type :ok, :f :append, :key "3", :value "x 21 9 y"} {:process 21, :type :invoke, :f :get, :key "2", :value nil} {:process 8, :type :ok, :f :get, :key "2", :value "x 39 0 yx 30 0 y"} {:process 8, :type :invoke, :f :append, :key "5", :value "x 8 1 y"} {:process 24, :type :ok, :f :get, :key "4", :value "x 21 1 yx 21 5 y"} {:process 24, :type :invoke, :f :get, :key "9", :value nil} {:process 35, :type :ok, :f :append, :key "9", :value "x 35 0 y"} {:process 35, :type :invoke, :f :get, :key "6", :value nil} {:process 5, :type :ok, :f :get, :key "2", :value "x 39 0 yx 30 0 y"} {:process 5, :type :invoke, :f :get, :key "6", :value nil} {:process 19, :type :ok, :f :append, :key "6", :value "x 19 0 y"} {:process 19, :type :invoke, :f :append, :key "9", :value "x 19 1 y"} {:process 21, :type :ok, :f :get, :key "2", :value "x 39 0 yx 30 0 y"} {:process 21, :type :invoke, :f :get, :key "3", :value nil} {:process 8, :type :ok, :f :append, :key "5", :value "x 8 1 y"} {:process 8, :type :invoke, :f :get, :key "6", :value nil} {:process 35, :type :ok, :f :get, :key "6", :value "x 19 0 y"} {:process 35, :type :invoke, :f :put, :key "9", :value "x 35 1 y"} {:process 13, :type :ok, :f :get, :key "5", :value "x 47 0 yx 8 1 y"} {:process 13, :type :invoke, :f :get, :key "9", :value nil} {:process 21, :type :ok, :f :get, :key "3", :value "x 8 0 yx 21 9 y"} {:process 21, :type :invoke, :f :append, :key "7", :value "x 21 10 y"} {:process 8, :type :ok, :f :get, :key "6", :value "x 19 0 y"} {:process 8, :type :invoke, :f :append, :key "0", :value "x 8 2 y"} {:process 1, :type :ok, :f :get, :key "6", :value "x 19 0 y"} {:process 1, :type :invoke, :f :get, :key "7", :value nil} {:process 35, :type :ok, :f :put, :key "9", :value "x 35 1 y"} {:process 35, :type :invoke, :f :get, :key "1", :value nil} {:process 13, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 y"} {:process 13, :type :invoke, :f :get, :key "7", :value nil} {:process 40, :type :ok, :f :append, :key "5", :value "x 40 0 y"} {:process 40, :type :invoke, :f :get, :key "6", :value nil} {:process 21, :type :ok, :f :append, :key "7", :value "x 21 10 y"} {:process 21, :type :invoke, :f :get, :key "3", :value nil} {:process 8, :type :ok, :f :append, :key "0", :value "x 8 2 y"} {:process 8, :type :invoke, :f :get, :key "6", :value nil} {:process 13, :type :ok, :f :get, :key "7", :value "x 3 0 yx 5 0 yx 21 10 y"} {:process 13, :type :invoke, :f :append, :key "8", :value "x 13 1 y"} {:process 1, :type :ok, :f :get, :key "7", :value "x 3 0 yx 5 0 yx 21 10 y"} {:process 1, :type :invoke, :f :append, :key "0", :value "x 1 0 y"} {:process 35, :type :ok, :f :get, :key "1", :value "x 21 0 y"} {:process 35, :type :invoke, :f :append, :key "4", :value "x 35 2 y"} {:process 21, :type :ok, :f :get, :key "3", :value "x 8 0 yx 21 9 y"} {:process 21, :type :invoke, :f :get, :key "5", :value nil} {:process 32, :type :ok, :f :append, :key "6", :value "x 32 0 y"} {:process 32, :type :invoke, :f :get, :key "8", :value nil} {:process 40, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 y"} {:process 40, :type :invoke, :f :append, :key "7", :value "x 40 1 y"} {:process 41, :type :ok, :f :append, :key "0", :value "x 41 0 y"} {:process 41, :type :invoke, :f :append, :key "4", :value "x 41 1 y"} {:process 35, :type :ok, :f :append, :key "4", :value "x 35 2 y"} {:process 35, :type :invoke, :f :get, :key "6", :value nil} {:process 21, :type :ok, :f :get, :key "5", :value "x 47 0 yx 8 1 yx 40 0 y"} {:process 21, :type :invoke, :f :append, :key "5", :value "x 21 11 y"} {:process 13, :type :ok, :f :append, :key "8", :value "x 13 1 y"} {:process 13, :type :invoke, :f :get, :key "9", :value nil} {:process 1, :type :ok, :f :append, :key "0", :value "x 1 0 y"} {:process 1, :type :invoke, :f :get, :key "7", :value nil} {:process 40, :type :ok, :f :append, :key "7", :value "x 40 1 y"} {:process 40, :type :invoke, :f :append, :key "9", :value "x 40 2 y"} {:process 15, :type :ok, :f :append, :key "2", :value "x 15 0 y"} {:process 15, :type :invoke, :f :append, :key "2", :value "x 15 1 y"} {:process 34, :type :ok, :f :get, :key "4", :value "x 21 1 yx 21 5 yx 35 2 y"} {:process 34, :type :invoke, :f :get, :key "9", :value nil} {:process 35, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 y"} {:process 35, :type :invoke, :f :get, :key "1", :value nil} {:process 12, :type :ok, :f :append, :key "5", :value "x 12 0 y"} {:process 12, :type :invoke, :f :get, :key "6", :value nil} {:process 15, :type :ok, :f :append, :key "2", :value "x 15 1 y"} {:process 15, :type :invoke, :f :append, :key "6", :value "x 15 2 y"} {:process 21, :type :ok, :f :append, :key "5", :value "x 21 11 y"} {:process 21, :type :invoke, :f :append, :key "8", :value "x 21 12 y"} {:process 35, :type :ok, :f :get, :key "1", :value "x 21 0 y"} {:process 35, :type :invoke, :f :append, :key "5", :value "x 35 3 y"} {:process 40, :type :ok, :f :append, :key "9", :value "x 40 2 y"} {:process 40, :type :invoke, :f :append, :key "5", :value "x 40 3 y"} {:process 41, :type :ok, :f :append, :key "4", :value "x 41 1 y"} {:process 41, :type :invoke, :f :get, :key "4", :value nil} {:process 15, :type :ok, :f :append, :key "6", :value "x 15 2 y"} {:process 15, :type :invoke, :f :get, :key "6", :value nil} {:process 34, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 y"} {:process 34, :type :invoke, :f :append, :key "7", :value "x 34 0 y"} {:process 1, :type :ok, :f :get, :key "7", :value "x 3 0 yx 5 0 yx 21 10 yx 40 1 y"} {:process 1, :type :invoke, :f :get, :key "9", :value nil} {:process 35, :type :ok, :f :append, :key "5", :value "x 35 3 y"} {:process 35, :type :invoke, :f :append, :key "8", :value "x 35 4 y"} {:process 40, :type :ok, :f :append, :key "5", :value "x 40 3 y"} {:process 40, :type :invoke, :f :append, :key "0", :value "x 40 4 y"} {:process 36, :type :ok, :f :get, :key "5", :value "x 47 0 yx 8 1 yx 40 0 yx 12 0 yx 21 11 yx 35 3 yx 40 3 y"} {:process 36, :type :invoke, :f :append, :key "7", :value "x 36 0 y"} {:process 15, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 y"} {:process 15, :type :invoke, :f :get, :key "1", :value nil} {:process 34, :type :ok, :f :append, :key "7", :value "x 34 0 y"} {:process 34, :type :invoke, :f :append, :key "2", :value "x 34 1 y"} {:process 41, :type :ok, :f :get, :key "4", :value "x 21 1 yx 21 5 yx 35 2 yx 41 1 y"} {:process 41, :type :invoke, :f :append, :key "4", :value "x 41 2 y"} {:process 35, :type :ok, :f :append, :key "8", :value "x 35 4 y"} {:process 35, :type :invoke, :f :get, :key "4", :value nil} {:process 40, :type :ok, :f :append, :key "0", :value "x 40 4 y"} {:process 40, :type :invoke, :f :get, :key "9", :value nil} {:process 1, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 y"} {:process 1, :type :invoke, :f :get, :key "2", :value nil} {:process 15, :type :ok, :f :get, :key "1", :value "x 21 0 y"} {:process 15, :type :invoke, :f :append, :key "1", :value "x 15 3 y"} {:process 40, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 y"} {:process 36, :type :ok, :f :append, :key "7", :value "x 36 0 y"} {:process 40, :type :invoke, :f :get, :key "1", :value nil} {:process 36, :type :invoke, :f :append, :key "1", :value "x 36 1 y"} {:process 1, :type :ok, :f :get, :key "2", :value "x 39 0 yx 30 0 yx 15 0 yx 15 1 y"} {:process 1, :type :invoke, :f :append, :key "8", :value "x 1 1 y"} {:process 41, :type :ok, :f :append, :key "4", :value "x 41 2 y"} {:process 41, :type :invoke, :f :append, :key "3", :value "x 41 3 y"} {:process 2, :type :ok, :f :append, :key "4", :value "x 2 0 y"} {:process 2, :type :invoke, :f :get, :key "8", :value nil} {:process 15, :type :ok, :f :append, :key "1", :value "x 15 3 y"} {:process 15, :type :invoke, :f :get, :key "3", :value nil} {:process 41, :type :ok, :f :append, :key "3", :value "x 41 3 y"} {:process 41, :type :invoke, :f :append, :key "7", :value "x 41 4 y"} {:process 40, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 y"} {:process 40, :type :invoke, :f :append, :key "8", :value "x 40 5 y"} {:process 36, :type :ok, :f :append, :key "1", :value "x 36 1 y"} {:process 36, :type :invoke, :f :get, :key "7", :value nil} {:process 41, :type :ok, :f :append, :key "7", :value "x 41 4 y"} {:process 41, :type :invoke, :f :get, :key "3", :value nil} {:process 40, :type :ok, :f :append, :key "8", :value "x 40 5 y"} {:process 40, :type :invoke, :f :get, :key "4", :value nil} {:process 20, :type :ok, :f :get, :key "2", :value "x 39 0 yx 30 0 yx 15 0 yx 15 1 y"} {:process 20, :type :invoke, :f :get, :key "9", :value nil} {:process 1, :type :ok, :f :append, :key "8", :value "x 1 1 y"} {:process 1, :type :invoke, :f :append, :key "7", :value "x 1 2 y"} {:process 41, :type :ok, :f :get, :key "3", :value "x 8 0 yx 21 9 yx 41 3 y"} {:process 41, :type :invoke, :f :append, :key "1", :value "x 41 5 y"} {:process 15, :type :ok, :f :get, :key "3", :value "x 8 0 yx 21 9 yx 41 3 y"} {:process 15, :type :invoke, :f :append, :key "7", :value "x 15 4 y"} {:process 36, :type :ok, :f :get, :key "7", :value "x 3 0 yx 5 0 yx 21 10 yx 40 1 yx 34 0 yx 36 0 yx 41 4 y"} {:process 36, :type :invoke, :f :append, :key "1", :value "x 36 2 y"} {:process 40, :type :ok, :f :get, :key "4", :value "x 21 1 yx 21 5 yx 35 2 yx 41 1 yx 41 2 yx 2 0 y"} {:process 40, :type :invoke, :f :append, :key "1", :value "x 40 6 y"} {:process 20, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 y"} {:process 20, :type :invoke, :f :append, :key "6", :value "x 20 0 y"} {:process 1, :type :ok, :f :append, :key "7", :value "x 1 2 y"} {:process 1, :type :invoke, :f :get, :key "4", :value nil} {:process 41, :type :ok, :f :append, :key "1", :value "x 41 5 y"} {:process 41, :type :invoke, :f :put, :key "0", :value "x 41 6 y"} {:process 15, :type :ok, :f :append, :key "7", :value "x 15 4 y"} {:process 15, :type :invoke, :f :append, :key "0", :value "x 15 5 y"} {:process 36, :type :ok, :f :append, :key "1", :value "x 36 2 y"} {:process 36, :type :invoke, :f :get, :key "1", :value nil} {:process 41, :type :ok, :f :put, :key "0", :value "x 41 6 y"} {:process 41, :type :invoke, :f :get, :key "3", :value nil} {:process 15, :type :ok, :f :append, :key "0", :value "x 15 5 y"} {:process 15, :type :invoke, :f :get, :key "0", :value nil} {:process 36, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 y"} {:process 36, :type :invoke, :f :append, :key "4", :value "x 36 3 y"} {:process 23, :type :ok, :f :get, :key "2", :value "x 39 0 yx 30 0 yx 15 0 yx 15 1 y"} {:process 23, :type :invoke, :f :get, :key "6", :value nil} {:process 48, :type :ok, :f :get, :key "0", :value "x 41 6 yx 15 5 y"} {:process 31, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 y"} {:process 48, :type :invoke, :f :append, :key "7", :value "x 48 0 y"} {:process 31, :type :invoke, :f :append, :key "9", :value "x 31 0 y"} {:process 18, :type :ok, :f :append, :key "1", :value "x 18 0 y"} {:process 18, :type :invoke, :f :append, :key "4", :value "x 18 1 y"} {:process 48, :type :ok, :f :append, :key "7", :value "x 48 0 y"} {:process 48, :type :invoke, :f :get, :key "5", :value nil} {:process 31, :type :ok, :f :append, :key "9", :value "x 31 0 y"} {:process 31, :type :invoke, :f :append, :key "7", :value "x 31 1 y"} {:process 39, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 y"} {:process 39, :type :invoke, :f :append, :key "0", :value "x 39 1 y"} {:process 39, :type :ok, :f :append, :key "0", :value "x 39 1 y"} {:process 39, :type :invoke, :f :get, :key "4", :value nil} {:process 32, :type :ok, :f :get, :key "8", :value "x 21 7 yx 21 8 yx 13 1 yx 21 12 yx 35 4 yx 1 1 yx 40 5 y"} {:process 32, :type :invoke, :f :get, :key "3", :value nil} {:process 24, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 y"} {:process 24, :type :invoke, :f :append, :key "1", :value "x 24 0 y"} {:process 39, :type :ok, :f :get, :key "4", :value "x 21 1 yx 21 5 yx 35 2 yx 41 1 yx 41 2 yx 2 0 yx 18 1 y"} {:process 39, :type :invoke, :f :append, :key "3", :value "x 39 2 y"} {:process 28, :type :ok, :f :get, :key "3", :value "x 8 0 yx 21 9 yx 41 3 y"} {:process 28, :type :invoke, :f :append, :key "6", :value "x 28 0 y"} {:process 24, :type :ok, :f :append, :key "1", :value "x 24 0 y"} {:process 24, :type :invoke, :f :get, :key "4", :value nil} {:process 14, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 y"} {:process 14, :type :invoke, :f :get, :key "4", :value nil} {:process 39, :type :ok, :f :append, :key "3", :value "x 39 2 y"} {:process 39, :type :invoke, :f :get, :key "9", :value nil} {:process 28, :type :ok, :f :append, :key "6", :value "x 28 0 y"} {:process 28, :type :invoke, :f :get, :key "5", :value nil} {:process 24, :type :ok, :f :get, :key "4", :value "x 21 1 yx 21 5 yx 35 2 yx 41 1 yx 41 2 yx 2 0 yx 18 1 y"} {:process 24, :type :invoke, :f :append, :key "4", :value "x 24 1 y"} {:process 14, :type :ok, :f :get, :key "4", :value "x 21 1 yx 21 5 yx 35 2 yx 41 1 yx 41 2 yx 2 0 yx 18 1 y"} {:process 14, :type :invoke, :f :append, :key "7", :value "x 14 0 y"} {:process 28, :type :ok, :f :get, :key "5", :value "x 47 0 yx 8 1 yx 40 0 yx 12 0 yx 21 11 yx 35 3 yx 40 3 y"} {:process 28, :type :invoke, :f :get, :key "0", :value nil} {:process 24, :type :ok, :f :append, :key "4", :value "x 24 1 y"} {:process 24, :type :invoke, :f :get, :key "8", :value nil} {:process 39, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 y"} {:process 39, :type :invoke, :f :append, :key "4", :value "x 39 3 y"} {:process 14, :type :ok, :f :append, :key "7", :value "x 14 0 y"} {:process 14, :type :invoke, :f :get, :key "4", :value nil} {:process 20, :type :ok, :f :append, :key "6", :value "x 20 0 y"} {:process 20, :type :invoke, :f :get, :key "4", :value nil} {:process 19, :type :ok, :f :append, :key "9", :value "x 19 1 y"} {:process 19, :type :invoke, :f :append, :key "6", :value "x 19 2 y"} {:process 28, :type :ok, :f :get, :key "0", :value "x 41 6 yx 15 5 yx 39 1 y"} {:process 28, :type :invoke, :f :get, :key "6", :value nil} {:process 35, :type :ok, :f :get, :key "4", :value "x 21 1 yx 21 5 yx 35 2 yx 41 1 yx 41 2 yx 2 0 yx 18 1 yx 24 1 y"} {:process 35, :type :invoke, :f :append, :key "3", :value "x 35 5 y"} {:process 27, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 y"} {:process 27, :type :invoke, :f :get, :key "0", :value nil} {:process 14, :type :ok, :f :get, :key "4", :value "x 21 1 yx 21 5 yx 35 2 yx 41 1 yx 41 2 yx 2 0 yx 18 1 yx 24 1 y"} {:process 14, :type :invoke, :f :append, :key "6", :value "x 14 1 y"} {:process 35, :type :ok, :f :append, :key "3", :value "x 35 5 y"} {:process 20, :type :ok, :f :get, :key "4", :value "x 21 1 yx 21 5 yx 35 2 yx 41 1 yx 41 2 yx 2 0 yx 18 1 yx 24 1 y"} {:process 20, :type :invoke, :f :put, :key "3", :value "x 20 1 y"} {:process 35, :type :invoke, :f :get, :key "2", :value nil} {:process 28, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 y"} {:process 28, :type :invoke, :f :get, :key "3", :value nil} {:process 27, :type :ok, :f :get, :key "0", :value "x 41 6 yx 15 5 yx 39 1 y"} {:process 27, :type :invoke, :f :get, :key "1", :value nil} {:process 20, :type :ok, :f :put, :key "3", :value "x 20 1 y"} {:process 20, :type :invoke, :f :get, :key "5", :value nil} {:process 35, :type :ok, :f :get, :key "2", :value "x 39 0 yx 30 0 yx 15 0 yx 15 1 y"} {:process 35, :type :invoke, :f :append, :key "2", :value "x 35 6 y"} {:process 28, :type :ok, :f :get, :key "3", :value "x 20 1 y"} {:process 28, :type :invoke, :f :append, :key "5", :value "x 28 1 y"} {:process 27, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 y"} {:process 27, :type :invoke, :f :get, :key "1", :value nil} {:process 33, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 y"} {:process 33, :type :invoke, :f :get, :key "9", :value nil} {:process 40, :type :ok, :f :append, :key "1", :value "x 40 6 y"} {:process 40, :type :invoke, :f :append, :key "0", :value "x 40 7 y"} {:process 35, :type :ok, :f :append, :key "2", :value "x 35 6 y"} {:process 35, :type :invoke, :f :append, :key "0", :value "x 35 7 y"} {:process 28, :type :ok, :f :append, :key "5", :value "x 28 1 y"} {:process 28, :type :invoke, :f :put, :key "7", :value "x 28 2 y"} {:process 2, :type :ok, :f :get, :key "8", :value "x 21 7 yx 21 8 yx 13 1 yx 21 12 yx 35 4 yx 1 1 yx 40 5 y"} {:process 2, :type :invoke, :f :get, :key "9", :value nil} {:process 41, :type :ok, :f :get, :key "3", :value "x 20 1 y"} {:process 41, :type :invoke, :f :get, :key "6", :value nil} {:process 27, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 y"} {:process 27, :type :invoke, :f :append, :key "3", :value "x 27 1 y"} {:process 28, :type :ok, :f :put, :key "7", :value "x 28 2 y"} {:process 28, :type :invoke, :f :put, :key "4", :value "x 28 3 y"} {:process 27, :type :ok, :f :append, :key "3", :value "x 27 1 y"} {:process 27, :type :invoke, :f :append, :key "7", :value "x 27 2 y"} {:process 35, :type :ok, :f :append, :key "0", :value "x 35 7 y"} {:process 35, :type :invoke, :f :get, :key "7", :value nil} {:process 9, :type :ok, :f :append, :key "9", :value "x 9 0 y"} {:process 40, :type :ok, :f :append, :key "0", :value "x 40 7 y"} {:process 9, :type :invoke, :f :get, :key "1", :value nil} {:process 40, :type :invoke, :f :get, :key "3", :value nil} {:process 41, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 y"} {:process 41, :type :invoke, :f :get, :key "8", :value nil} {:process 33, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 y"} {:process 33, :type :invoke, :f :append, :key "4", :value "x 33 0 y"} {:process 28, :type :ok, :f :put, :key "4", :value "x 28 3 y"} {:process 28, :type :invoke, :f :append, :key "1", :value "x 28 4 y"} {:process 35, :type :ok, :f :get, :key "7", :value "x 28 2 y"} {:process 35, :type :invoke, :f :append, :key "5", :value "x 35 8 y"} {:process 27, :type :ok, :f :append, :key "7", :value "x 27 2 y"} {:process 27, :type :invoke, :f :get, :key "6", :value nil} {:process 33, :type :ok, :f :append, :key "4", :value "x 33 0 y"} {:process 33, :type :invoke, :f :append, :key "6", :value "x 33 1 y"} {:process 35, :type :ok, :f :append, :key "5", :value "x 35 8 y"} {:process 35, :type :invoke, :f :append, :key "3", :value "x 35 9 y"} {:process 41, :type :ok, :f :get, :key "8", :value "x 21 7 yx 21 8 yx 13 1 yx 21 12 yx 35 4 yx 1 1 yx 40 5 y"} {:process 41, :type :invoke, :f :append, :key "8", :value "x 41 7 y"} {:process 28, :type :ok, :f :append, :key "1", :value "x 28 4 y"} {:process 28, :type :invoke, :f :get, :key "7", :value nil} {:process 27, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 y"} {:process 27, :type :invoke, :f :get, :key "6", :value nil} {:process 0, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 y"} {:process 0, :type :invoke, :f :get, :key "5", :value nil} {:process 40, :type :ok, :f :get, :key "3", :value "x 20 1 yx 27 1 y"} {:process 40, :type :invoke, :f :append, :key "4", :value "x 40 8 y"} {:process 9, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 y"} {:process 9, :type :invoke, :f :append, :key "2", :value "x 9 1 y"} {:process 23, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 y"} {:process 23, :type :invoke, :f :append, :key "0", :value "x 23 0 y"} {:process 31, :type :ok, :f :append, :key "7", :value "x 31 1 y"} {:process 31, :type :invoke, :f :append, :key "8", :value "x 31 2 y"} {:process 35, :type :ok, :f :append, :key "3", :value "x 35 9 y"} {:process 35, :type :invoke, :f :append, :key "3", :value "x 35 10 y"} {:process 41, :type :ok, :f :append, :key "8", :value "x 41 7 y"} {:process 33, :type :ok, :f :append, :key "6", :value "x 33 1 y"} {:process 41, :type :invoke, :f :get, :key "4", :value nil} {:process 33, :type :invoke, :f :append, :key "5", :value "x 33 2 y"} {:process 13, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 y"} {:process 13, :type :invoke, :f :get, :key "5", :value nil} {:process 0, :type :ok, :f :get, :key "5", :value "x 47 0 yx 8 1 yx 40 0 yx 12 0 yx 21 11 yx 35 3 yx 40 3 yx 28 1 yx 35 8 y"} {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 1 y"} {:process 28, :type :ok, :f :get, :key "7", :value "x 28 2 yx 27 2 yx 31 1 y"} {:process 28, :type :invoke, :f :append, :key "4", :value "x 28 5 y"} {:process 27, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 yx 33 1 y"} {:process 27, :type :invoke, :f :append, :key "0", :value "x 27 3 y"} {:process 40, :type :ok, :f :append, :key "4", :value "x 40 8 y"} {:process 40, :type :invoke, :f :get, :key "0", :value nil} {:process 34, :type :ok, :f :append, :key "2", :value "x 34 1 y"} {:process 34, :type :invoke, :f :append, :key "1", :value "x 34 2 y"} {:process 31, :type :ok, :f :append, :key "8", :value "x 31 2 y"} {:process 31, :type :invoke, :f :append, :key "1", :value "x 31 3 y"} {:process 34, :type :ok, :f :append, :key "1", :value "x 34 2 y"} {:process 9, :type :ok, :f :append, :key "2", :value "x 9 1 y"} {:process 34, :type :invoke, :f :put, :key "4", :value "x 34 3 y"} {:process 9, :type :invoke, :f :get, :key "1", :value nil} {:process 49, :type :ok, :f :get, :key "4", :value "x 28 3 yx 33 0 yx 40 8 y"} {:process 49, :type :invoke, :f :append, :key "0", :value "x 49 0 y"} {:process 41, :type :ok, :f :get, :key "4", :value "x 28 3 yx 33 0 yx 40 8 y"} {:process 41, :type :invoke, :f :get, :key "6", :value nil} {:process 23, :type :ok, :f :append, :key "0", :value "x 23 0 y"} {:process 23, :type :invoke, :f :get, :key "5", :value nil} {:process 35, :type :ok, :f :append, :key "3", :value "x 35 10 y"} {:process 35, :type :invoke, :f :append, :key "3", :value "x 35 11 y"} {:process 9, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 yx 34 2 y"} {:process 9, :type :invoke, :f :append, :key "8", :value "x 9 2 y"} {:process 27, :type :ok, :f :append, :key "0", :value "x 27 3 y"} {:process 27, :type :invoke, :f :append, :key "7", :value "x 27 4 y"} {:process 31, :type :ok, :f :append, :key "1", :value "x 31 3 y"} {:process 31, :type :invoke, :f :get, :key "7", :value nil} {:process 41, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 yx 33 1 y"} {:process 41, :type :invoke, :f :append, :key "9", :value "x 41 8 y"} {:process 28, :type :ok, :f :append, :key "4", :value "x 28 5 y"} {:process 28, :type :invoke, :f :get, :key "3", :value nil} {:process 23, :type :ok, :f :get, :key "5", :value "x 47 0 yx 8 1 yx 40 0 yx 12 0 yx 21 11 yx 35 3 yx 40 3 yx 28 1 yx 35 8 y"} {:process 23, :type :invoke, :f :get, :key "6", :value nil} {:process 27, :type :ok, :f :append, :key "7", :value "x 27 4 y"} {:process 27, :type :invoke, :f :append, :key "8", :value "x 27 5 y"} {:process 40, :type :ok, :f :get, :key "0", :value "x 41 6 yx 15 5 yx 39 1 yx 35 7 yx 40 7 yx 23 0 yx 27 3 yx 0 1 y"} {:process 40, :type :invoke, :f :put, :key "0", :value "x 40 9 y"} {:process 49, :type :ok, :f :append, :key "0", :value "x 49 0 y"} {:process 49, :type :invoke, :f :get, :key "4", :value nil} {:process 31, :type :ok, :f :get, :key "7", :value "x 28 2 yx 27 2 yx 31 1 yx 27 4 y"} {:process 31, :type :invoke, :f :get, :key "3", :value nil} {:process 41, :type :ok, :f :append, :key "9", :value "x 41 8 y"} {:process 41, :type :invoke, :f :get, :key "2", :value nil} {:process 23, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 yx 33 1 y"} {:process 23, :type :invoke, :f :append, :key "1", :value "x 23 1 y"} {:process 35, :type :ok, :f :append, :key "3", :value "x 35 11 y"} {:process 35, :type :invoke, :f :append, :key "5", :value "x 35 12 y"} {:process 9, :type :ok, :f :append, :key "8", :value "x 9 2 y"} {:process 41, :type :ok, :f :get, :key "2", :value "x 39 0 yx 30 0 yx 15 0 yx 15 1 yx 35 6 yx 34 1 yx 9 1 y"} {:process 9, :type :invoke, :f :get, :key "1", :value nil} {:process 41, :type :invoke, :f :get, :key "6", :value nil} {:process 28, :type :ok, :f :get, :key "3", :value "x 20 1 yx 27 1 yx 35 9 yx 35 10 yx 35 11 y"} {:process 28, :type :invoke, :f :append, :key "2", :value "x 28 6 y"} {:process 31, :type :ok, :f :get, :key "3", :value "x 20 1 yx 27 1 yx 35 9 yx 35 10 yx 35 11 y"} {:process 31, :type :invoke, :f :append, :key "4", :value "x 31 4 y"} {:process 49, :type :ok, :f :get, :key "4", :value "x 34 3 y"} {:process 49, :type :invoke, :f :append, :key "0", :value "x 49 1 y"} {:process 27, :type :ok, :f :append, :key "8", :value "x 27 5 y"} {:process 27, :type :invoke, :f :get, :key "9", :value nil} {:process 41, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 yx 33 1 y"} {:process 41, :type :invoke, :f :append, :key "8", :value "x 41 9 y"} {:process 40, :type :ok, :f :put, :key "0", :value "x 40 9 y"} {:process 40, :type :invoke, :f :get, :key "4", :value nil} {:process 49, :type :ok, :f :append, :key "0", :value "x 49 1 y"} {:process 49, :type :invoke, :f :get, :key "3", :value nil} {:process 35, :type :ok, :f :append, :key "5", :value "x 35 12 y"} {:process 35, :type :invoke, :f :put, :key "3", :value "x 35 13 y"} {:process 38, :type :ok, :f :get, :key "5", :value "x 47 0 yx 8 1 yx 40 0 yx 12 0 yx 21 11 yx 35 3 yx 40 3 yx 28 1 yx 35 8 yx 35 12 y"} {:process 38, :type :invoke, :f :append, :key "0", :value "x 38 0 y"} {:process 27, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 y"} {:process 27, :type :invoke, :f :put, :key "0", :value "x 27 6 y"} {:process 38, :type :ok, :f :append, :key "0", :value "x 38 0 y"} {:process 38, :type :invoke, :f :append, :key "8", :value "x 38 1 y"} {:process 38, :type :ok, :f :append, :key "8", :value "x 38 1 y"} {:process 38, :type :invoke, :f :append, :key "0", :value "x 38 2 y"} {:process 44, :type :ok, :f :append, :key "9", :value "x 44 0 y"} {:process 44, :type :invoke, :f :get, :key "6", :value nil} {:process 10, :type :ok, :f :append, :key "9", :value "x 10 0 y"} {:process 10, :type :invoke, :f :get, :key "2", :value nil} {:process 38, :type :ok, :f :append, :key "0", :value "x 38 2 y"} {:process 38, :type :invoke, :f :append, :key "6", :value "x 38 3 y"} {:process 44, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 yx 33 1 y"} {:process 44, :type :invoke, :f :get, :key "8", :value nil} {:process 10, :type :ok, :f :get, :key "2", :value "x 39 0 yx 30 0 yx 15 0 yx 15 1 yx 35 6 yx 34 1 yx 9 1 yx 28 6 y"} {:process 10, :type :invoke, :f :get, :key "7", :value nil} {:process 38, :type :ok, :f :append, :key "6", :value "x 38 3 y"} {:process 38, :type :invoke, :f :append, :key "7", :value "x 38 4 y"} {:process 44, :type :ok, :f :get, :key "8", :value "x 21 7 yx 21 8 yx 13 1 yx 21 12 yx 35 4 yx 1 1 yx 40 5 yx 41 7 yx 31 2 yx 9 2 yx 27 5 yx 41 9 yx 38 1 y"} {:process 44, :type :invoke, :f :put, :key "4", :value "x 44 1 y"} {:process 8, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 yx 33 1 yx 38 3 y"} {:process 8, :type :invoke, :f :append, :key "0", :value "x 8 3 y"} {:process 10, :type :ok, :f :get, :key "7", :value "x 28 2 yx 27 2 yx 31 1 yx 27 4 y"} {:process 10, :type :invoke, :f :get, :key "2", :value nil} {:process 38, :type :ok, :f :append, :key "7", :value "x 38 4 y"} {:process 38, :type :invoke, :f :append, :key "4", :value "x 38 5 y"} {:process 48, :type :ok, :f :get, :key "5", :value "x 47 0 yx 8 1 yx 40 0 yx 12 0 yx 21 11 yx 35 3 yx 40 3 yx 28 1 yx 35 8 yx 35 12 y"} {:process 48, :type :invoke, :f :get, :key "9", :value nil} {:process 8, :type :ok, :f :append, :key "0", :value "x 8 3 y"} {:process 8, :type :invoke, :f :get, :key "9", :value nil} {:process 44, :type :ok, :f :put, :key "4", :value "x 44 1 y"} {:process 44, :type :invoke, :f :get, :key "7", :value nil} {:process 10, :type :ok, :f :get, :key "2", :value "x 39 0 yx 30 0 yx 15 0 yx 15 1 yx 35 6 yx 34 1 yx 9 1 yx 28 6 y"} {:process 10, :type :invoke, :f :get, :key "5", :value nil} {:process 38, :type :ok, :f :append, :key "4", :value "x 38 5 y"} {:process 38, :type :invoke, :f :append, :key "0", :value "x 38 6 y"} {:process 8, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 y"} {:process 8, :type :invoke, :f :append, :key "0", :value "x 8 4 y"} {:process 44, :type :ok, :f :get, :key "7", :value "x 28 2 yx 27 2 yx 31 1 yx 27 4 yx 38 4 y"} {:process 44, :type :invoke, :f :get, :key "4", :value nil} {:process 48, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 y"} {:process 48, :type :invoke, :f :get, :key "3", :value nil} {:process 38, :type :ok, :f :append, :key "0", :value "x 38 6 y"} {:process 38, :type :invoke, :f :append, :key "2", :value "x 38 7 y"} {:process 10, :type :ok, :f :get, :key "5", :value "x 47 0 yx 8 1 yx 40 0 yx 12 0 yx 21 11 yx 35 3 yx 40 3 yx 28 1 yx 35 8 yx 35 12 y"} {:process 10, :type :invoke, :f :append, :key "0", :value "x 10 1 y"} {:process 44, :type :ok, :f :get, :key "4", :value "x 44 1 yx 38 5 y"} {:process 44, :type :invoke, :f :get, :key "9", :value nil} {:process 48, :type :ok, :f :get, :key "3", :value "x 20 1 yx 27 1 yx 35 9 yx 35 10 yx 35 11 y"} {:process 48, :type :invoke, :f :append, :key "6", :value "x 48 1 y"} {:process 38, :type :ok, :f :append, :key "2", :value "x 38 7 y"} {:process 38, :type :invoke, :f :append, :key "1", :value "x 38 8 y"} {:process 44, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 y"} {:process 44, :type :invoke, :f :append, :key "5", :value "x 44 2 y"} {:process 48, :type :ok, :f :append, :key "6", :value "x 48 1 y"} {:process 48, :type :invoke, :f :get, :key "2", :value nil} {:process 21, :type :ok, :f :append, :key "8", :value "x 21 12 y"} {:process 21, :type :invoke, :f :get, :key "9", :value nil} {:process 47, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 yx 33 1 yx 38 3 yx 48 1 y"} {:process 47, :type :invoke, :f :append, :key "8", :value "x 47 1 y"} {:process 12, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 yx 33 1 yx 38 3 yx 48 1 y"} {:process 12, :type :invoke, :f :get, :key "5", :value nil} {:process 15, :type :ok, :f :get, :key "0", :value "x 40 9 yx 49 1 yx 38 0 yx 38 2 yx 8 3 yx 38 6 y"} {:process 15, :type :invoke, :f :append, :key "4", :value "x 15 6 y"} {:process 44, :type :ok, :f :append, :key "5", :value "x 44 2 y"} {:process 44, :type :invoke, :f :get, :key "3", :value nil} {:process 30, :type :ok, :f :append, :key "2", :value "x 30 0 y"} {:process 30, :type :invoke, :f :append, :key "3", :value "x 30 1 y"} {:process 29, :type :ok, :f :put, :key "5", :value "x 29 0 y"} {:process 29, :type :invoke, :f :get, :key "1", :value nil} {:process 48, :type :ok, :f :get, :key "2", :value "x 39 0 yx 30 0 yx 15 0 yx 15 1 yx 35 6 yx 34 1 yx 9 1 yx 28 6 yx 38 7 y"} {:process 48, :type :invoke, :f :append, :key "9", :value "x 48 2 y"} {:process 30, :type :ok, :f :append, :key "3", :value "x 30 1 y"} {:process 30, :type :invoke, :f :get, :key "0", :value nil} {:process 15, :type :ok, :f :append, :key "4", :value "x 15 6 y"} {:process 15, :type :invoke, :f :get, :key "4", :value nil} {:process 12, :type :ok, :f :get, :key "5", :value "x 29 0 y"} {:process 12, :type :invoke, :f :get, :key "3", :value nil} {:process 44, :type :ok, :f :get, :key "3", :value "x 20 1 yx 27 1 yx 35 9 yx 35 10 yx 35 11 yx 30 1 y"} {:process 44, :type :invoke, :f :append, :key "4", :value "x 44 3 y"} {:process 29, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 yx 34 2 yx 31 3 yx 23 1 yx 22 0 yx 38 8 y"} {:process 29, :type :invoke, :f :put, :key "2", :value "x 29 1 y"} {:process 12, :type :ok, :f :get, :key "3", :value "x 20 1 yx 27 1 yx 35 9 yx 35 10 yx 35 11 yx 30 1 y"} {:process 12, :type :invoke, :f :get, :key "7", :value nil} {:process 15, :type :ok, :f :get, :key "4", :value "x 44 1 yx 38 5 yx 15 6 y"} {:process 15, :type :invoke, :f :append, :key "3", :value "x 15 7 y"} {:process 44, :type :ok, :f :append, :key "4", :value "x 44 3 y"} {:process 44, :type :invoke, :f :get, :key "6", :value nil} {:process 29, :type :ok, :f :put, :key "2", :value "x 29 1 y"} {:process 29, :type :invoke, :f :append, :key "8", :value "x 29 2 y"} {:process 44, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 yx 33 1 yx 38 3 yx 48 1 y"} {:process 44, :type :invoke, :f :append, :key "3", :value "x 44 4 y"} {:process 29, :type :ok, :f :append, :key "8", :value "x 29 2 y"} {:process 29, :type :invoke, :f :get, :key "4", :value nil} {:process 15, :type :ok, :f :append, :key "3", :value "x 15 7 y"} {:process 15, :type :invoke, :f :append, :key "4", :value "x 15 8 y"} {:process 5, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 yx 33 1 yx 38 3 yx 48 1 y"} {:process 5, :type :invoke, :f :append, :key "7", :value "x 5 1 y"} {:process 3, :type :ok, :f :append, :key "8", :value "x 3 1 y"} {:process 3, :type :invoke, :f :get, :key "4", :value nil} {:process 29, :type :ok, :f :get, :key "4", :value "x 44 1 yx 38 5 yx 15 6 yx 44 3 y"} {:process 29, :type :invoke, :f :get, :key "7", :value nil} {:process 3, :type :ok, :f :get, :key "4", :value "x 44 1 yx 38 5 yx 15 6 yx 44 3 y"} {:process 3, :type :invoke, :f :append, :key "0", :value "x 3 2 y"} {:process 44, :type :ok, :f :append, :key "3", :value "x 44 4 y"} {:process 44, :type :invoke, :f :get, :key "5", :value nil} {:process 3, :type :ok, :f :append, :key "0", :value "x 3 2 y"} {:process 3, :type :invoke, :f :get, :key "5", :value nil} {:process 29, :type :ok, :f :get, :key "7", :value "x 28 2 yx 27 2 yx 31 1 yx 27 4 yx 38 4 yx 5 1 y"} {:process 29, :type :invoke, :f :append, :key "2", :value "x 29 3 y"} {:process 3, :type :ok, :f :get, :key "5", :value "x 29 0 y"} {:process 3, :type :invoke, :f :get, :key "3", :value nil} {:process 7, :type :ok, :f :append, :key "0", :value "x 7 0 y"} {:process 7, :type :invoke, :f :get, :key "6", :value nil} {:process 29, :type :ok, :f :append, :key "2", :value "x 29 3 y"} {:process 29, :type :invoke, :f :append, :key "2", :value "x 29 4 y"} {:process 7, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 yx 33 1 yx 38 3 yx 48 1 y"} {:process 7, :type :invoke, :f :append, :key "2", :value "x 7 1 y"} {:process 3, :type :ok, :f :get, :key "3", :value "x 20 1 yx 27 1 yx 35 9 yx 35 10 yx 35 11 yx 30 1 yx 15 7 yx 44 4 y"} {:process 3, :type :invoke, :f :get, :key "0", :value nil} {:process 7, :type :ok, :f :append, :key "2", :value "x 7 1 y"} {:process 7, :type :invoke, :f :get, :key "1", :value nil} {:process 17, :type :ok, :f :get, :key "8", :value "x 21 7 yx 21 8 yx 13 1 yx 21 12 yx 35 4 yx 1 1 yx 40 5 yx 41 7 yx 31 2 yx 9 2 yx 27 5 yx 41 9 yx 38 1 yx 47 1 yx 29 2 yx 3 1 y"} {:process 17, :type :invoke, :f :append, :key "2", :value "x 17 0 y"} {:process 11, :type :ok, :f :append, :key "8", :value "x 11 0 y"} {:process 11, :type :invoke, :f :get, :key "9", :value nil} {:process 3, :type :ok, :f :get, :key "0", :value "x 40 9 yx 49 1 yx 38 0 yx 38 2 yx 8 3 yx 38 6 yx 3 2 yx 7 0 y"} {:process 3, :type :invoke, :f :get, :key "2", :value nil} {:process 19, :type :ok, :f :append, :key "6", :value "x 19 2 y"} {:process 19, :type :invoke, :f :get, :key "0", :value nil} {:process 7, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 yx 34 2 yx 31 3 yx 23 1 yx 22 0 yx 38 8 y"} {:process 7, :type :invoke, :f :get, :key "9", :value nil} {:process 26, :type :ok, :f :put, :key "7", :value "x 26 0 y"} {:process 26, :type :invoke, :f :get, :key "1", :value nil} {:process 19, :type :ok, :f :get, :key "0", :value "x 40 9 yx 49 1 yx 38 0 yx 38 2 yx 8 3 yx 38 6 yx 3 2 yx 7 0 y"} {:process 19, :type :invoke, :f :append, :key "1", :value "x 19 3 y"} {:process 17, :type :ok, :f :append, :key "2", :value "x 17 0 y"} {:process 17, :type :invoke, :f :get, :key "5", :value nil} {:process 11, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 y"} {:process 11, :type :invoke, :f :get, :key "0", :value nil} {:process 26, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 yx 34 2 yx 31 3 yx 23 1 yx 22 0 yx 38 8 y"} {:process 26, :type :invoke, :f :append, :key "6", :value "x 26 1 y"} {:process 14, :type :ok, :f :append, :key "6", :value "x 14 1 y"} {:process 14, :type :invoke, :f :append, :key "8", :value "x 14 2 y"} {:process 7, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 y"} {:process 7, :type :invoke, :f :append, :key "5", :value "x 7 2 y"} {:process 11, :type :ok, :f :get, :key "0", :value "x 40 9 yx 49 1 yx 38 0 yx 38 2 yx 8 3 yx 38 6 yx 3 2 yx 7 0 y"} {:process 14, :type :ok, :f :append, :key "8", :value "x 14 2 y"} {:process 14, :type :invoke, :f :append, :key "8", :value "x 14 3 y"} {:process 11, :type :invoke, :f :get, :key "4", :value nil} {:process 7, :type :ok, :f :append, :key "5", :value "x 7 2 y"} {:process 7, :type :invoke, :f :get, :key "8", :value nil} {:process 26, :type :ok, :f :append, :key "6", :value "x 26 1 y"} {:process 26, :type :invoke, :f :get, :key "0", :value nil} {:process 42, :type :ok, :f :append, :key "0", :value "x 42 0 y"} {:process 42, :type :invoke, :f :get, :key "6", :value nil} {:process 11, :type :ok, :f :get, :key "4", :value "x 44 1 yx 38 5 yx 15 6 yx 44 3 yx 4 0 y"} {:process 11, :type :invoke, :f :get, :key "2", :value nil} {:process 7, :type :ok, :f :get, :key "8", :value "x 21 7 yx 21 8 yx 13 1 yx 21 12 yx 35 4 yx 1 1 yx 40 5 yx 41 7 yx 31 2 yx 9 2 yx 27 5 yx 41 9 yx 38 1 yx 47 1 yx 29 2 yx 3 1 yx 11 0 yx 14 2 y"} {:process 7, :type :invoke, :f :append, :key "4", :value "x 7 3 y"} {:process 26, :type :ok, :f :get, :key "0", :value "x 40 9 yx 49 1 yx 38 0 yx 38 2 yx 8 3 yx 38 6 yx 3 2 yx 7 0 yx 42 0 y"} {:process 26, :type :invoke, :f :get, :key "1", :value nil} {:process 42, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 yx 33 1 yx 38 3 yx 48 1 yx 19 2 yx 14 1 yx 26 1 y"} {:process 42, :type :invoke, :f :append, :key "5", :value "x 42 1 y"} {:process 43, :type :ok, :f :append, :key "3", :value "x 43 0 y"} {:process 43, :type :invoke, :f :get, :key "5", :value nil} {:process 14, :type :ok, :f :append, :key "8", :value "x 14 3 y"} {:process 14, :type :invoke, :f :put, :key "8", :value "x 14 4 y"} {:process 7, :type :ok, :f :append, :key "4", :value "x 7 3 y"} {:process 7, :type :invoke, :f :get, :key "1", :value nil} {:process 43, :type :ok, :f :get, :key "5", :value "x 29 0 yx 7 2 y"} {:process 43, :type :invoke, :f :append, :key "0", :value "x 43 1 y"} {:process 6, :type :ok, :f :get, :key "5", :value "x 29 0 yx 7 2 y"} {:process 6, :type :invoke, :f :append, :key "5", :value "x 6 1 y"} {:process 26, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 yx 34 2 yx 31 3 yx 23 1 yx 22 0 yx 38 8 yx 19 3 y"} {:process 26, :type :invoke, :f :put, :key "5", :value "x 26 2 y"} {:process 46, :type :ok, :f :append, :key "9", :value "x 46 0 y"} {:process 46, :type :invoke, :f :append, :key "3", :value "x 46 1 y"} {:process 14, :type :ok, :f :put, :key "8", :value "x 14 4 y"} {:process 14, :type :invoke, :f :append, :key "0", :value "x 14 5 y"} {:process 26, :type :ok, :f :put, :key "5", :value "x 26 2 y"} {:process 26, :type :invoke, :f :get, :key "8", :value nil} {:process 14, :type :ok, :f :append, :key "0", :value "x 14 5 y"} {:process 14, :type :invoke, :f :append, :key "2", :value "x 14 6 y"} {:process 43, :type :ok, :f :append, :key "0", :value "x 43 1 y"} {:process 46, :type :ok, :f :append, :key "3", :value "x 46 1 y"} {:process 43, :type :invoke, :f :append, :key "8", :value "x 43 2 y"} {:process 46, :type :invoke, :f :get, :key "1", :value nil} {:process 45, :type :ok, :f :put, :key "2", :value "x 45 0 y"} {:process 45, :type :invoke, :f :append, :key "8", :value "x 45 1 y"} {:process 6, :type :ok, :f :append, :key "5", :value "x 6 1 y"} {:process 6, :type :invoke, :f :append, :key "0", :value "x 6 2 y"} {:process 43, :type :ok, :f :append, :key "8", :value "x 43 2 y"} {:process 43, :type :invoke, :f :get, :key "5", :value nil} {:process 46, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 yx 34 2 yx 31 3 yx 23 1 yx 22 0 yx 38 8 yx 19 3 y"} {:process 14, :type :ok, :f :append, :key "2", :value "x 14 6 y"} {:process 14, :type :invoke, :f :get, :key "0", :value nil} {:process 46, :type :invoke, :f :get, :key "7", :value nil} {:process 43, :type :ok, :f :get, :key "5", :value "x 26 2 yx 6 1 y"} {:process 43, :type :invoke, :f :get, :key "7", :value nil} {:process 6, :type :ok, :f :append, :key "0", :value "x 6 2 y"} {:process 6, :type :invoke, :f :append, :key "5", :value "x 6 3 y"} {:process 46, :type :ok, :f :get, :key "7", :value "x 26 0 y"} {:process 46, :type :invoke, :f :append, :key "4", :value "x 46 2 y"} {:process 14, :type :ok, :f :get, :key "0", :value "x 40 9 yx 49 1 yx 38 0 yx 38 2 yx 8 3 yx 38 6 yx 3 2 yx 7 0 yx 42 0 yx 43 1 yx 14 5 yx 6 2 y"} {:process 14, :type :invoke, :f :append, :key "0", :value "x 14 7 y"} {:process 6, :type :ok, :f :append, :key "5", :value "x 6 3 y"} {:process 6, :type :invoke, :f :append, :key "0", :value "x 6 4 y"} {:process 34, :type :ok, :f :put, :key "4", :value "x 34 3 y"} {:process 34, :type :invoke, :f :get, :key "1", :value nil} {:process 24, :type :ok, :f :get, :key "8", :value "x 14 4 yx 43 2 yx 45 1 y"} {:process 24, :type :invoke, :f :get, :key "4", :value nil} {:process 2, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 y"} {:process 2, :type :invoke, :f :append, :key "0", :value "x 2 1 y"} {:process 32, :type :ok, :f :get, :key "3", :value "x 20 1 yx 27 1 yx 35 9 yx 35 10 yx 35 11 yx 30 1 yx 15 7 yx 44 4 yx 43 0 yx 46 1 y"} {:process 32, :type :invoke, :f :append, :key "4", :value "x 32 1 y"} {:process 25, :type :ok, :f :append, :key "7", :value "x 25 0 y"} {:process 25, :type :invoke, :f :get, :key "3", :value nil} {:process 6, :type :ok, :f :append, :key "0", :value "x 6 4 y"} {:process 6, :type :invoke, :f :append, :key "3", :value "x 6 5 y"} {:process 46, :type :ok, :f :append, :key "4", :value "x 46 2 y"} {:process 46, :type :invoke, :f :append, :key "0", :value "x 46 3 y"} {:process 34, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 yx 34 2 yx 31 3 yx 23 1 yx 22 0 yx 38 8 yx 19 3 y"} {:process 34, :type :invoke, :f :append, :key "7", :value "x 34 4 y"} {:process 35, :type :ok, :f :put, :key "3", :value "x 35 13 y"} {:process 35, :type :invoke, :f :get, :key "5", :value nil} {:process 25, :type :ok, :f :get, :key "3", :value "x 35 13 y"} {:process 25, :type :invoke, :f :get, :key "6", :value nil} {:process 36, :type :ok, :f :append, :key "4", :value "x 36 3 y"} {:process 36, :type :invoke, :f :append, :key "4", :value "x 36 4 y"} {:process 46, :type :ok, :f :append, :key "0", :value "x 46 3 y"} {:process 46, :type :invoke, :f :append, :key "8", :value "x 46 4 y"} {:process 27, :type :ok, :f :put, :key "0", :value "x 27 6 y"} {:process 27, :type :invoke, :f :get, :key "0", :value nil} {:process 9, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 yx 34 2 yx 31 3 yx 23 1 yx 22 0 yx 38 8 yx 19 3 y"} {:process 9, :type :invoke, :f :get, :key "3", :value nil} {:process 49, :type :ok, :f :get, :key "3", :value "x 35 13 yx 6 5 y"} {:process 49, :type :invoke, :f :append, :key "4", :value "x 49 2 y"} {:process 35, :type :ok, :f :get, :key "5", :value "x 26 2 yx 6 1 yx 6 3 y"} {:process 35, :type :invoke, :f :append, :key "1", :value "x 35 14 y"} {:process 34, :type :ok, :f :append, :key "7", :value "x 34 4 y"} {:process 34, :type :invoke, :f :get, :key "9", :value nil} {:process 28, :type :ok, :f :append, :key "2", :value "x 28 6 y"} {:process 28, :type :invoke, :f :get, :key "0", :value nil} {:process 25, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 yx 33 1 yx 38 3 yx 48 1 yx 19 2 yx 14 1 yx 26 1 y"} {:process 25, :type :invoke, :f :get, :key "5", :value nil} {:process 27, :type :ok, :f :get, :key "0", :value "x 27 6 yx 46 3 y"} {:process 27, :type :invoke, :f :append, :key "7", :value "x 27 7 y"} {:process 41, :type :ok, :f :append, :key "8", :value "x 41 9 y"} {:process 41, :type :invoke, :f :append, :key "7", :value "x 41 10 y"} {:process 9, :type :ok, :f :get, :key "3", :value "x 35 13 yx 6 5 y"} {:process 9, :type :invoke, :f :append, :key "7", :value "x 9 3 y"} {:process 23, :type :ok, :f :append, :key "1", :value "x 23 1 y"} {:process 23, :type :invoke, :f :get, :key "1", :value nil} {:process 27, :type :ok, :f :append, :key "7", :value "x 27 7 y"} {:process 27, :type :invoke, :f :append, :key "5", :value "x 27 8 y"} {:process 35, :type :ok, :f :append, :key "1", :value "x 35 14 y"} {:process 35, :type :invoke, :f :get, :key "7", :value nil} {:process 34, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 y"} {:process 34, :type :invoke, :f :put, :key "2", :value "x 34 5 y"} {:process 49, :type :ok, :f :append, :key "4", :value "x 49 2 y"} {:process 49, :type :invoke, :f :append, :key "4", :value "x 49 3 y"} {:process 23, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 yx 34 2 yx 31 3 yx 23 1 yx 22 0 yx 38 8 yx 19 3 yx 35 14 y"} {:process 25, :type :ok, :f :get, :key "5", :value "x 26 2 yx 6 1 yx 6 3 y"} {:process 23, :type :invoke, :f :append, :key "9", :value "x 23 2 y"} {:process 25, :type :invoke, :f :append, :key "0", :value "x 25 1 y"} {:process 27, :type :ok, :f :append, :key "5", :value "x 27 8 y"} {:process 27, :type :invoke, :f :append, :key "7", :value "x 27 9 y"} {:process 49, :type :ok, :f :append, :key "4", :value "x 49 3 y"} {:process 49, :type :invoke, :f :append, :key "7", :value "x 49 4 y"} {:process 41, :type :ok, :f :append, :key "7", :value "x 41 10 y"} {:process 41, :type :invoke, :f :get, :key "1", :value nil} {:process 35, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 y"} {:process 35, :type :invoke, :f :get, :key "7", :value nil} {:process 34, :type :ok, :f :put, :key "2", :value "x 34 5 y"} {:process 34, :type :invoke, :f :get, :key "6", :value nil} {:process 27, :type :ok, :f :append, :key "7", :value "x 27 9 y"} {:process 27, :type :invoke, :f :append, :key "7", :value "x 27 10 y"} {:process 23, :type :ok, :f :append, :key "9", :value "x 23 2 y"} {:process 23, :type :invoke, :f :get, :key "7", :value nil} {:process 25, :type :ok, :f :append, :key "0", :value "x 25 1 y"} {:process 25, :type :invoke, :f :append, :key "6", :value "x 25 2 y"} {:process 18, :type :ok, :f :append, :key "4", :value "x 18 1 y"} {:process 18, :type :invoke, :f :append, :key "2", :value "x 18 2 y"} {:process 41, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 yx 34 2 yx 31 3 yx 23 1 yx 22 0 yx 38 8 yx 19 3 yx 35 14 y"} {:process 41, :type :invoke, :f :get, :key "1", :value nil} {:process 23, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 y"} {:process 23, :type :invoke, :f :append, :key "5", :value "x 23 3 y"} {:process 35, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 y"} {:process 35, :type :invoke, :f :append, :key "1", :value "x 35 15 y"} {:process 18, :type :ok, :f :append, :key "2", :value "x 18 2 y"} {:process 18, :type :invoke, :f :get, :key "1", :value nil} {:process 27, :type :ok, :f :append, :key "7", :value "x 27 10 y"} {:process 27, :type :invoke, :f :append, :key "8", :value "x 27 11 y"} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 1 y"} {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 2 y"} {:process 18, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 yx 34 2 yx 31 3 yx 23 1 yx 22 0 yx 38 8 yx 19 3 yx 35 14 y"} {:process 18, :type :invoke, :f :get, :key "6", :value nil} {:process 25, :type :ok, :f :append, :key "6", :value "x 25 2 y"} {:process 25, :type :invoke, :f :append, :key "1", :value "x 25 3 y"} {:process 27, :type :ok, :f :append, :key "8", :value "x 27 11 y"} {:process 41, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 yx 34 2 yx 31 3 yx 23 1 yx 22 0 yx 38 8 yx 19 3 yx 35 14 y"} {:process 27, :type :invoke, :f :get, :key "5", :value nil} {:process 41, :type :invoke, :f :get, :key "5", :value nil} {:process 25, :type :ok, :f :append, :key "1", :value "x 25 3 y"} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 2 y"} {:process 25, :type :invoke, :f :append, :key "0", :value "x 25 4 y"} {:process 0, :type :invoke, :f :append, :key "8", :value "x 0 3 y"} {:process 18, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 yx 33 1 yx 38 3 yx 48 1 yx 19 2 yx 14 1 yx 26 1 yx 25 2 y"} {:process 18, :type :invoke, :f :append, :key "3", :value "x 18 3 y"} {:process 39, :type :ok, :f :append, :key "4", :value "x 39 3 y"} {:process 39, :type :invoke, :f :get, :key "4", :value nil} {:process 39, :type :ok, :f :get, :key "4", :value "x 44 1 yx 38 5 yx 15 6 yx 44 3 yx 4 0 yx 7 3 yx 46 2 yx 36 3 yx 49 2 yx 49 3 yx 39 3 y"} {:process 39, :type :invoke, :f :get, :key "7", :value nil} {:process 0, :type :ok, :f :append, :key "8", :value "x 0 3 y"} {:process 0, :type :invoke, :f :get, :key "1", :value nil} {:process 25, :type :ok, :f :append, :key "0", :value "x 25 4 y"} {:process 25, :type :invoke, :f :append, :key "0", :value "x 25 5 y"} {:process 39, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 y"} {:process 39, :type :invoke, :f :append, :key "6", :value "x 39 4 y"} {:process 0, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 yx 34 2 yx 31 3 yx 23 1 yx 22 0 yx 38 8 yx 19 3 yx 35 14 yx 25 3 y"} {:process 0, :type :invoke, :f :append, :key "4", :value "x 0 4 y"} {:process 4, :type :ok, :f :append, :key "4", :value "x 4 0 y"} {:process 4, :type :invoke, :f :get, :key "7", :value nil} {:process 3, :type :ok, :f :get, :key "2", :value "x 34 5 yx 18 2 y"} {:process 3, :type :invoke, :f :append, :key "3", :value "x 3 3 y"} {:process 3, :type :ok, :f :append, :key "3", :value "x 3 3 y"} {:process 3, :type :invoke, :f :get, :key "7", :value nil} {:process 4, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 y"} {:process 4, :type :invoke, :f :append, :key "1", :value "x 4 1 y"} {:process 3, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 y"} {:process 3, :type :invoke, :f :append, :key "5", :value "x 3 4 y"} {:process 19, :type :ok, :f :append, :key "1", :value "x 19 3 y"} {:process 19, :type :invoke, :f :get, :key "4", :value nil} {:process 20, :type :ok, :f :get, :key "5", :value "x 26 2 yx 6 1 yx 6 3 yx 27 8 y"} {:process 20, :type :invoke, :f :get, :key "7", :value nil} {:process 4, :type :ok, :f :append, :key "1", :value "x 4 1 y"} {:process 4, :type :invoke, :f :get, :key "5", :value nil} {:process 3, :type :ok, :f :append, :key "5", :value "x 3 4 y"} {:process 3, :type :invoke, :f :append, :key "1", :value "x 3 5 y"} {:process 20, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 y"} {:process 19, :type :ok, :f :get, :key "4", :value "x 44 1 yx 38 5 yx 15 6 yx 44 3 yx 4 0 yx 7 3 yx 46 2 yx 36 3 yx 49 2 yx 49 3 yx 39 3 y"} {:process 20, :type :invoke, :f :append, :key "3", :value "x 20 2 y"} {:process 19, :type :invoke, :f :append, :key "5", :value "x 19 4 y"} {:process 4, :type :ok, :f :get, :key "5", :value "x 26 2 yx 6 1 yx 6 3 yx 27 8 yx 3 4 y"} {:process 4, :type :invoke, :f :append, :key "7", :value "x 4 2 y"} {:process 1, :type :ok, :f :get, :key "4", :value "x 44 1 yx 38 5 yx 15 6 yx 44 3 yx 4 0 yx 7 3 yx 46 2 yx 36 3 yx 49 2 yx 49 3 yx 39 3 y"} {:process 1, :type :invoke, :f :put, :key "3", :value "x 1 3 y"} {:process 7, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 yx 34 2 yx 31 3 yx 23 1 yx 22 0 yx 38 8 yx 19 3 yx 35 14 yx 25 3 yx 4 1 y"} {:process 7, :type :invoke, :f :append, :key "6", :value "x 7 4 y"} {:process 3, :type :ok, :f :append, :key "1", :value "x 3 5 y"} {:process 3, :type :invoke, :f :get, :key "2", :value nil} {:process 42, :type :ok, :f :append, :key "5", :value "x 42 1 y"} {:process 42, :type :invoke, :f :append, :key "3", :value "x 42 2 y"} {:process 20, :type :ok, :f :append, :key "3", :value "x 20 2 y"} {:process 20, :type :invoke, :f :append, :key "6", :value "x 20 3 y"} {:process 17, :type :ok, :f :get, :key "5", :value "x 26 2 yx 6 1 yx 6 3 yx 27 8 yx 3 4 yx 42 1 y"} {:process 17, :type :invoke, :f :get, :key "2", :value nil} {:process 19, :type :ok, :f :append, :key "5", :value "x 19 4 y"} {:process 19, :type :invoke, :f :get, :key "7", :value nil} {:process 4, :type :ok, :f :append, :key "7", :value "x 4 2 y"} {:process 4, :type :invoke, :f :append, :key "3", :value "x 4 3 y"} {:process 7, :type :ok, :f :append, :key "6", :value "x 7 4 y"} {:process 17, :type :ok, :f :get, :key "2", :value "x 34 5 yx 18 2 y"} {:process 17, :type :invoke, :f :append, :key "5", :value "x 17 1 y"} {:process 7, :type :invoke, :f :append, :key "6", :value "x 7 5 y"} {:process 42, :type :ok, :f :append, :key "3", :value "x 42 2 y"} {:process 42, :type :invoke, :f :append, :key "2", :value "x 42 3 y"} {:process 4, :type :ok, :f :append, :key "3", :value "x 4 3 y"} {:process 4, :type :invoke, :f :get, :key "7", :value nil} {:process 20, :type :ok, :f :append, :key "6", :value "x 20 3 y"} {:process 20, :type :invoke, :f :get, :key "0", :value nil} {:process 17, :type :ok, :f :append, :key "5", :value "x 17 1 y"} {:process 17, :type :invoke, :f :append, :key "6", :value "x 17 2 y"} {:process 7, :type :ok, :f :append, :key "6", :value "x 7 5 y"} {:process 7, :type :invoke, :f :append, :key "6", :value "x 7 6 y"} {:process 42, :type :ok, :f :append, :key "2", :value "x 42 3 y"} {:process 42, :type :invoke, :f :get, :key "4", :value nil} {:process 13, :type :ok, :f :get, :key "5", :value "x 26 2 yx 6 1 yx 6 3 yx 27 8 yx 3 4 yx 42 1 yx 19 4 yx 17 1 y"} {:process 13, :type :invoke, :f :get, :key "5", :value nil} {:process 20, :type :ok, :f :get, :key "0", :value "x 27 6 yx 46 3 yx 25 1 yx 0 2 yx 25 4 yx 25 5 y"} {:process 7, :type :ok, :f :append, :key "6", :value "x 7 6 y"} {:process 17, :type :ok, :f :append, :key "6", :value "x 17 2 y"} {:process 20, :type :invoke, :f :append, :key "1", :value "x 20 4 y"} {:process 7, :type :invoke, :f :append, :key "2", :value "x 7 7 y"} {:process 17, :type :invoke, :f :get, :key "1", :value nil} {:process 42, :type :ok, :f :get, :key "4", :value "x 44 1 yx 38 5 yx 15 6 yx 44 3 yx 4 0 yx 7 3 yx 46 2 yx 36 3 yx 49 2 yx 49 3 yx 39 3 y"} {:process 42, :type :invoke, :f :get, :key "3", :value nil} {:process 13, :type :ok, :f :get, :key "5", :value "x 26 2 yx 6 1 yx 6 3 yx 27 8 yx 3 4 yx 42 1 yx 19 4 yx 17 1 y"} {:process 13, :type :invoke, :f :append, :key "2", :value "x 13 2 y"} {:process 42, :type :ok, :f :get, :key "3", :value "x 35 13 yx 6 5 yx 3 3 yx 20 2 yx 42 2 yx 4 3 y"} {:process 42, :type :invoke, :f :append, :key "5", :value "x 42 4 y"} {:process 7, :type :ok, :f :append, :key "2", :value "x 7 7 y"} {:process 7, :type :invoke, :f :append, :key "5", :value "x 7 8 y"} {:process 20, :type :ok, :f :append, :key "1", :value "x 20 4 y"} {:process 20, :type :invoke, :f :append, :key "0", :value "x 20 5 y"} {:process 42, :type :ok, :f :append, :key "5", :value "x 42 4 y"} {:process 42, :type :invoke, :f :get, :key "7", :value nil} {:process 26, :type :ok, :f :get, :key "8", :value "x 14 4 yx 43 2 yx 45 1 yx 46 4 yx 27 11 yx 0 3 y"} {:process 26, :type :invoke, :f :get, :key "5", :value nil} {:process 32, :type :ok, :f :append, :key "4", :value "x 32 1 y"} {:process 32, :type :invoke, :f :get, :key "6", :value nil} {:process 45, :type :ok, :f :append, :key "8", :value "x 45 1 y"} {:process 24, :type :ok, :f :get, :key "4", :value "x 44 1 yx 38 5 yx 15 6 yx 44 3 yx 4 0 yx 7 3 yx 46 2 yx 36 3 yx 49 2 yx 49 3 yx 39 3 y"} {:process 45, :type :invoke, :f :get, :key "1", :value nil} {:process 24, :type :invoke, :f :append, :key "8", :value "x 24 2 y"} {:process 13, :type :ok, :f :append, :key "2", :value "x 13 2 y"} {:process 13, :type :invoke, :f :append, :key "6", :value "x 13 3 y"} {:process 7, :type :ok, :f :append, :key "5", :value "x 7 8 y"} {:process 7, :type :invoke, :f :get, :key "5", :value nil} {:process 13, :type :ok, :f :append, :key "6", :value "x 13 3 y"} {:process 42, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 yx 4 2 y"} {:process 42, :type :invoke, :f :get, :key "0", :value nil} {:process 13, :type :invoke, :f :get, :key "0", :value nil} {:process 14, :type :ok, :f :append, :key "0", :value "x 14 7 y"} {:process 14, :type :invoke, :f :get, :key "0", :value nil} {:process 32, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 yx 33 1 yx 38 3 yx 48 1 yx 19 2 yx 14 1 yx 26 1 yx 25 2 yx 39 4 yx 7 4 yx 20 3 yx 7 5 yx 17 2 yx 7 6 yx 13 3 y"} {:process 32, :type :invoke, :f :append, :key "7", :value "x 32 2 y"} {:process 20, :type :ok, :f :append, :key "0", :value "x 20 5 y"} {:process 20, :type :invoke, :f :append, :key "9", :value "x 20 6 y"} {:process 26, :type :ok, :f :get, :key "5", :value "x 26 2 yx 6 1 yx 6 3 yx 27 8 yx 3 4 yx 42 1 yx 19 4 yx 17 1 yx 42 4 yx 7 8 y"} {:process 26, :type :invoke, :f :append, :key "9", :value "x 26 3 y"} {:process 24, :type :ok, :f :append, :key "8", :value "x 24 2 y"} {:process 24, :type :invoke, :f :append, :key "7", :value "x 24 3 y"} {:process 32, :type :ok, :f :append, :key "7", :value "x 32 2 y"} {:process 32, :type :invoke, :f :put, :key "6", :value "x 32 3 y"} {:process 45, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 yx 34 2 yx 31 3 yx 23 1 yx 22 0 yx 38 8 yx 19 3 yx 35 14 yx 25 3 yx 4 1 yx 3 5 yx 20 4 y"} {:process 7, :type :ok, :f :get, :key "5", :value "x 26 2 yx 6 1 yx 6 3 yx 27 8 yx 3 4 yx 42 1 yx 19 4 yx 17 1 yx 42 4 yx 7 8 y"} {:process 45, :type :invoke, :f :append, :key "8", :value "x 45 2 y"} {:process 7, :type :invoke, :f :get, :key "6", :value nil} {:process 42, :type :ok, :f :get, :key "0", :value "x 27 6 yx 46 3 yx 25 1 yx 0 2 yx 25 4 yx 25 5 yx 20 5 y"} {:process 42, :type :invoke, :f :get, :key "7", :value nil} {:process 13, :type :ok, :f :get, :key "0", :value "x 27 6 yx 46 3 yx 25 1 yx 0 2 yx 25 4 yx 25 5 yx 20 5 y"} {:process 13, :type :invoke, :f :append, :key "8", :value "x 13 4 y"} {:process 14, :type :ok, :f :get, :key "0", :value "x 27 6 yx 46 3 yx 25 1 yx 0 2 yx 25 4 yx 25 5 yx 20 5 y"} {:process 14, :type :invoke, :f :get, :key "8", :value nil} {:process 26, :type :ok, :f :append, :key "9", :value "x 26 3 y"} {:process 26, :type :invoke, :f :append, :key "7", :value "x 26 4 y"} {:process 31, :type :ok, :f :append, :key "4", :value "x 31 4 y"} {:process 31, :type :invoke, :f :get, :key "0", :value nil} {:process 7, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 yx 33 1 yx 38 3 yx 48 1 yx 19 2 yx 14 1 yx 26 1 yx 25 2 yx 39 4 yx 7 4 yx 20 3 yx 7 5 yx 17 2 yx 7 6 yx 13 3 y"} {:process 7, :type :invoke, :f :get, :key "6", :value nil} {:process 45, :type :ok, :f :append, :key "8", :value "x 45 2 y"} {:process 45, :type :invoke, :f :get, :key "9", :value nil} {:process 24, :type :ok, :f :append, :key "7", :value "x 24 3 y"} {:process 24, :type :invoke, :f :get, :key "2", :value nil} {:process 14, :type :ok, :f :get, :key "8", :value "x 14 4 yx 43 2 yx 45 1 yx 46 4 yx 27 11 yx 0 3 yx 24 2 yx 45 2 yx 13 4 y"} {:process 14, :type :invoke, :f :append, :key "0", :value "x 14 8 y"} {:process 13, :type :ok, :f :append, :key "8", :value "x 13 4 y"} {:process 13, :type :invoke, :f :append, :key "8", :value "x 13 5 y"} {:process 42, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 yx 4 2 yx 32 2 yx 24 3 y"} {:process 42, :type :invoke, :f :append, :key "3", :value "x 42 5 y"} {:process 32, :type :ok, :f :put, :key "6", :value "x 32 3 y"} {:process 26, :type :ok, :f :append, :key "7", :value "x 26 4 y"} {:process 7, :type :ok, :f :get, :key "6", :value "x 19 0 yx 32 0 yx 15 2 yx 20 0 yx 28 0 yx 33 1 yx 38 3 yx 48 1 yx 19 2 yx 14 1 yx 26 1 yx 25 2 yx 39 4 yx 7 4 yx 20 3 yx 7 5 yx 17 2 yx 7 6 yx 13 3 y"} {:process 26, :type :invoke, :f :append, :key "2", :value "x 26 5 y"} {:process 7, :type :invoke, :f :get, :key "9", :value nil} {:process 32, :type :invoke, :f :get, :key "6", :value nil} {:process 6, :type :ok, :f :append, :key "3", :value "x 6 5 y"} {:process 6, :type :invoke, :f :append, :key "5", :value "x 6 6 y"} {:process 14, :type :ok, :f :append, :key "0", :value "x 14 8 y"} {:process 14, :type :invoke, :f :get, :key "9", :value nil} {:process 45, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 y"} {:process 45, :type :invoke, :f :append, :key "4", :value "x 45 3 y"} {:process 28, :type :ok, :f :get, :key "0", :value "x 27 6 yx 46 3 yx 25 1 yx 0 2 yx 25 4 yx 25 5 yx 20 5 yx 14 8 y"} {:process 28, :type :invoke, :f :get, :key "8", :value nil} {:process 32, :type :ok, :f :get, :key "6", :value "x 32 3 y"} {:process 32, :type :invoke, :f :append, :key "4", :value "x 32 4 y"} {:process 13, :type :ok, :f :append, :key "8", :value "x 13 5 y"} {:process 13, :type :invoke, :f :get, :key "0", :value nil} {:process 42, :type :ok, :f :append, :key "3", :value "x 42 5 y"} {:process 42, :type :invoke, :f :get, :key "1", :value nil} {:process 31, :type :ok, :f :get, :key "0", :value "x 27 6 yx 46 3 yx 25 1 yx 0 2 yx 25 4 yx 25 5 yx 20 5 yx 14 8 y"} {:process 31, :type :invoke, :f :append, :key "4", :value "x 31 5 y"} {:process 14, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 y"} {:process 14, :type :invoke, :f :append, :key "6", :value "x 14 9 y"} {:process 24, :type :ok, :f :get, :key "2", :value "x 34 5 yx 18 2 yx 42 3 yx 7 7 yx 13 2 y"} {:process 24, :type :invoke, :f :append, :key "1", :value "x 24 4 y"} {:process 42, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 yx 34 2 yx 31 3 yx 23 1 yx 22 0 yx 38 8 yx 19 3 yx 35 14 yx 25 3 yx 4 1 yx 3 5 yx 20 4 y"} {:process 42, :type :invoke, :f :append, :key "3", :value "x 42 6 y"} {:process 7, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 y"} {:process 7, :type :invoke, :f :get, :key "0", :value nil} {:process 45, :type :ok, :f :append, :key "4", :value "x 45 3 y"} {:process 45, :type :invoke, :f :append, :key "9", :value "x 45 4 y"} {:process 31, :type :ok, :f :append, :key "4", :value "x 31 5 y"} {:process 31, :type :invoke, :f :get, :key "1", :value nil} {:process 2, :type :ok, :f :append, :key "0", :value "x 2 1 y"} {:process 2, :type :invoke, :f :append, :key "2", :value "x 2 2 y"} {:process 32, :type :ok, :f :append, :key "4", :value "x 32 4 y"} {:process 32, :type :invoke, :f :get, :key "6", :value nil} {:process 26, :type :ok, :f :append, :key "2", :value "x 26 5 y"} {:process 26, :type :invoke, :f :append, :key "9", :value "x 26 6 y"} {:process 28, :type :ok, :f :get, :key "8", :value "x 14 4 yx 43 2 yx 45 1 yx 46 4 yx 27 11 yx 0 3 yx 24 2 yx 45 2 yx 13 4 yx 13 5 y"} {:process 28, :type :invoke, :f :append, :key "4", :value "x 28 7 y"} {:process 6, :type :ok, :f :append, :key "5", :value "x 6 6 y"} {:process 6, :type :invoke, :f :append, :key "7", :value "x 6 7 y"} {:process 7, :type :ok, :f :get, :key "0", :value "x 27 6 yx 46 3 yx 25 1 yx 0 2 yx 25 4 yx 25 5 yx 20 5 yx 14 8 yx 2 1 y"} {:process 7, :type :invoke, :f :get, :key "9", :value nil} {:process 2, :type :ok, :f :append, :key "2", :value "x 2 2 y"} {:process 2, :type :invoke, :f :get, :key "9", :value nil} {:process 28, :type :ok, :f :append, :key "4", :value "x 28 7 y"} {:process 28, :type :invoke, :f :get, :key "8", :value nil} {:process 26, :type :ok, :f :append, :key "9", :value "x 26 6 y"} {:process 26, :type :invoke, :f :append, :key "9", :value "x 26 7 y"} {:process 42, :type :ok, :f :append, :key "3", :value "x 42 6 y"} {:process 42, :type :invoke, :f :get, :key "0", :value nil} {:process 45, :type :ok, :f :append, :key "9", :value "x 45 4 y"} {:process 45, :type :invoke, :f :append, :key "1", :value "x 45 5 y"} {:process 42, :type :ok, :f :get, :key "0", :value "x 27 6 yx 46 3 yx 25 1 yx 0 2 yx 25 4 yx 25 5 yx 20 5 yx 14 8 yx 2 1 y"} {:process 42, :type :invoke, :f :append, :key "1", :value "x 42 7 y"} {:process 46, :type :ok, :f :append, :key "8", :value "x 46 4 y"} {:process 46, :type :invoke, :f :get, :key "6", :value nil} {:process 31, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 yx 34 2 yx 31 3 yx 23 1 yx 22 0 yx 38 8 yx 19 3 yx 35 14 yx 25 3 yx 4 1 yx 3 5 yx 20 4 y"} {:process 31, :type :invoke, :f :get, :key "8", :value nil} {:process 2, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 y"} {:process 2, :type :invoke, :f :append, :key "7", :value "x 2 3 y"} {:process 7, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 y"} {:process 7, :type :invoke, :f :append, :key "9", :value "x 7 9 y"} {:process 28, :type :ok, :f :get, :key "8", :value "x 14 4 yx 43 2 yx 45 1 yx 46 4 yx 27 11 yx 0 3 yx 24 2 yx 45 2 yx 13 4 yx 13 5 y"} {:process 28, :type :invoke, :f :append, :key "7", :value "x 28 8 y"} {:process 6, :type :ok, :f :append, :key "7", :value "x 6 7 y"} {:process 6, :type :invoke, :f :append, :key "8", :value "x 6 8 y"} {:process 45, :type :ok, :f :append, :key "1", :value "x 45 5 y"} {:process 45, :type :invoke, :f :append, :key "4", :value "x 45 6 y"} {:process 31, :type :ok, :f :get, :key "8", :value "x 14 4 yx 43 2 yx 45 1 yx 46 4 yx 27 11 yx 0 3 yx 24 2 yx 45 2 yx 13 4 yx 13 5 y"} {:process 34, :type :ok, :f :get, :key "6", :value "x 32 3 y"} {:process 31, :type :invoke, :f :append, :key "9", :value "x 31 6 y"} {:process 34, :type :invoke, :f :get, :key "6", :value nil} {:process 26, :type :ok, :f :append, :key "9", :value "x 26 7 y"} {:process 26, :type :invoke, :f :append, :key "2", :value "x 26 8 y"} {:process 28, :type :ok, :f :append, :key "7", :value "x 28 8 y"} {:process 28, :type :invoke, :f :get, :key "9", :value nil} {:process 46, :type :ok, :f :get, :key "6", :value "x 32 3 y"} {:process 46, :type :invoke, :f :append, :key "3", :value "x 46 5 y"} {:process 42, :type :ok, :f :append, :key "1", :value "x 42 7 y"} {:process 7, :type :ok, :f :append, :key "9", :value "x 7 9 y"} {:process 42, :type :invoke, :f :append, :key "1", :value "x 42 8 y"} {:process 2, :type :ok, :f :append, :key "7", :value "x 2 3 y"} {:process 2, :type :invoke, :f :append, :key "1", :value "x 2 4 y"} {:process 7, :type :invoke, :f :put, :key "2", :value "x 7 10 y"} {:process 23, :type :ok, :f :append, :key "5", :value "x 23 3 y"} {:process 23, :type :invoke, :f :get, :key "1", :value nil} {:process 26, :type :ok, :f :append, :key "2", :value "x 26 8 y"} {:process 26, :type :invoke, :f :get, :key "0", :value nil} {:process 34, :type :ok, :f :get, :key "6", :value "x 32 3 y"} {:process 34, :type :invoke, :f :append, :key "6", :value "x 34 6 y"} {:process 6, :type :ok, :f :append, :key "8", :value "x 6 8 y"} {:process 6, :type :invoke, :f :append, :key "7", :value "x 6 9 y"} {:process 9, :type :ok, :f :append, :key "7", :value "x 9 3 y"} {:process 9, :type :invoke, :f :append, :key "7", :value "x 9 4 y"} {:process 46, :type :ok, :f :append, :key "3", :value "x 46 5 y"} {:process 46, :type :invoke, :f :get, :key "0", :value nil} {:process 45, :type :ok, :f :append, :key "4", :value "x 45 6 y"} {:process 45, :type :invoke, :f :append, :key "1", :value "x 45 7 y"} {:process 26, :type :ok, :f :get, :key "0", :value "x 27 6 yx 46 3 yx 25 1 yx 0 2 yx 25 4 yx 25 5 yx 20 5 yx 14 8 yx 2 1 y"} {:process 26, :type :invoke, :f :append, :key "9", :value "x 26 9 y"} {:process 42, :type :ok, :f :append, :key "1", :value "x 42 8 y"} {:process 42, :type :invoke, :f :append, :key "8", :value "x 42 9 y"} {:process 7, :type :ok, :f :put, :key "2", :value "x 7 10 y"} {:process 7, :type :invoke, :f :get, :key "8", :value nil} {:process 49, :type :ok, :f :append, :key "7", :value "x 49 4 y"} {:process 49, :type :invoke, :f :append, :key "2", :value "x 49 5 y"} {:process 6, :type :ok, :f :append, :key "7", :value "x 6 9 y"} {:process 6, :type :invoke, :f :append, :key "6", :value "x 6 10 y"} {:process 46, :type :ok, :f :get, :key "0", :value "x 27 6 yx 46 3 yx 25 1 yx 0 2 yx 25 4 yx 25 5 yx 20 5 yx 14 8 yx 2 1 y"} {:process 2, :type :ok, :f :append, :key "1", :value "x 2 4 y"} {:process 46, :type :invoke, :f :append, :key "9", :value "x 46 6 y"} {:process 2, :type :invoke, :f :append, :key "2", :value "x 2 5 y"} {:process 23, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 yx 34 2 yx 31 3 yx 23 1 yx 22 0 yx 38 8 yx 19 3 yx 35 14 yx 25 3 yx 4 1 yx 3 5 yx 20 4 yx 45 5 yx 42 7 yx 42 8 yx 2 4 y"} {:process 23, :type :invoke, :f :append, :key "2", :value "x 23 4 y"} {:process 49, :type :ok, :f :append, :key "2", :value "x 49 5 y"} {:process 45, :type :ok, :f :append, :key "1", :value "x 45 7 y"} {:process 49, :type :invoke, :f :get, :key "0", :value nil} {:process 45, :type :invoke, :f :get, :key "4", :value nil} {:process 42, :type :ok, :f :append, :key "8", :value "x 42 9 y"} {:process 42, :type :invoke, :f :append, :key "9", :value "x 42 10 y"} {:process 7, :type :ok, :f :get, :key "8", :value "x 14 4 yx 43 2 yx 45 1 yx 46 4 yx 27 11 yx 0 3 yx 24 2 yx 45 2 yx 13 4 yx 13 5 yx 6 8 yx 42 9 y"} {:process 7, :type :invoke, :f :append, :key "6", :value "x 7 11 y"} {:process 26, :type :ok, :f :append, :key "9", :value "x 26 9 y"} {:process 26, :type :invoke, :f :append, :key "5", :value "x 26 10 y"} {:process 23, :type :ok, :f :append, :key "2", :value "x 23 4 y"} {:process 23, :type :invoke, :f :get, :key "2", :value nil} {:process 6, :type :ok, :f :append, :key "6", :value "x 6 10 y"} {:process 6, :type :invoke, :f :get, :key "1", :value nil} {:process 42, :type :ok, :f :append, :key "9", :value "x 42 10 y"} {:process 42, :type :invoke, :f :get, :key "4", :value nil} {:process 2, :type :ok, :f :append, :key "2", :value "x 2 5 y"} {:process 2, :type :invoke, :f :get, :key "9", :value nil} {:process 49, :type :ok, :f :get, :key "0", :value "x 27 6 yx 46 3 yx 25 1 yx 0 2 yx 25 4 yx 25 5 yx 20 5 yx 14 8 yx 2 1 y"} {:process 49, :type :invoke, :f :append, :key "5", :value "x 49 6 y"} {:process 7, :type :ok, :f :append, :key "6", :value "x 7 11 y"} {:process 7, :type :invoke, :f :put, :key "5", :value "x 7 12 y"} {:process 45, :type :ok, :f :get, :key "4", :value "x 44 1 yx 38 5 yx 15 6 yx 44 3 yx 4 0 yx 7 3 yx 46 2 yx 36 3 yx 49 2 yx 49 3 yx 39 3 yx 32 1 yx 31 5 yx 45 3 yx 32 4 yx 28 7 yx 45 6 y"} {:process 45, :type :invoke, :f :append, :key "7", :value "x 45 8 y"} {:process 27, :type :ok, :f :get, :key "5", :value "x 26 2 yx 6 1 yx 6 3 yx 27 8 yx 3 4 yx 42 1 yx 19 4 yx 17 1 yx 42 4 yx 7 8 yx 6 6 yx 33 2 yx 23 3 y"} {:process 27, :type :invoke, :f :get, :key "6", :value nil} {:process 23, :type :ok, :f :get, :key "2", :value "x 7 10 yx 49 5 yx 23 4 yx 2 5 y"} {:process 23, :type :invoke, :f :append, :key "2", :value "x 23 5 y"} {:process 26, :type :ok, :f :append, :key "5", :value "x 26 10 y"} {:process 26, :type :invoke, :f :put, :key "1", :value "x 26 11 y"} {:process 27, :type :ok, :f :get, :key "6", :value "x 32 3 yx 6 10 yx 7 11 y"} {:process 27, :type :invoke, :f :append, :key "4", :value "x 27 12 y"} {:process 42, :type :ok, :f :get, :key "4", :value "x 44 1 yx 38 5 yx 15 6 yx 44 3 yx 4 0 yx 7 3 yx 46 2 yx 36 3 yx 49 2 yx 49 3 yx 39 3 yx 32 1 yx 31 5 yx 45 3 yx 32 4 yx 28 7 yx 45 6 y"} {:process 42, :type :invoke, :f :get, :key "1", :value nil} {:process 45, :type :ok, :f :append, :key "7", :value "x 45 8 y"} {:process 45, :type :invoke, :f :append, :key "3", :value "x 45 9 y"} {:process 6, :type :ok, :f :get, :key "1", :value "x 21 0 yx 15 3 yx 36 1 yx 41 5 yx 36 2 yx 18 0 yx 24 0 yx 40 6 yx 28 4 yx 34 2 yx 31 3 yx 23 1 yx 22 0 yx 38 8 yx 19 3 yx 35 14 yx 25 3 yx 4 1 yx 3 5 yx 20 4 yx 45 5 yx 42 7 yx 42 8 yx 2 4 yx 45 7 y"} {:process 6, :type :invoke, :f :get, :key "4", :value nil} {:process 49, :type :ok, :f :append, :key "5", :value "x 49 6 y"} {:process 49, :type :invoke, :f :get, :key "1", :value nil} {:process 7, :type :ok, :f :put, :key "5", :value "x 7 12 y"} {:process 7, :type :invoke, :f :append, :key "8", :value "x 7 13 y"} {:process 45, :type :ok, :f :append, :key "3", :value "x 45 9 y"} {:process 45, :type :invoke, :f :get, :key "8", :value nil} {:process 41, :type :ok, :f :get, :key "5", :value "x 7 12 y"} {:process 41, :type :invoke, :f :append, :key "7", :value "x 41 11 y"} {:process 26, :type :ok, :f :put, :key "1", :value "x 26 11 y"} {:process 26, :type :invoke, :f :get, :key "3", :value nil} {:process 23, :type :ok, :f :append, :key "2", :value "x 23 5 y"} {:process 23, :type :invoke, :f :get, :key "7", :value nil} {:process 45, :type :ok, :f :get, :key "8", :value "x 14 4 yx 43 2 yx 45 1 yx 46 4 yx 27 11 yx 0 3 yx 24 2 yx 45 2 yx 13 4 yx 13 5 yx 6 8 yx 42 9 y"} {:process 45, :type :invoke, :f :get, :key "0", :value nil} {:process 42, :type :ok, :f :get, :key "1", :value "x 26 11 y"} {:process 42, :type :invoke, :f :get, :key "5", :value nil} {:process 41, :type :ok, :f :append, :key "7", :value "x 41 11 y"} {:process 41, :type :invoke, :f :get, :key "3", :value nil} {:process 27, :type :ok, :f :append, :key "4", :value "x 27 12 y"} {:process 27, :type :invoke, :f :get, :key "6", :value nil} {:process 23, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 yx 4 2 yx 32 2 yx 24 3 yx 26 4 yx 6 7 yx 28 8 yx 2 3 yx 6 9 yx 45 8 yx 41 11 y"} {:process 23, :type :invoke, :f :get, :key "2", :value nil} {:process 49, :type :ok, :f :get, :key "1", :value "x 26 11 y"} {:process 49, :type :invoke, :f :append, :key "8", :value "x 49 7 y"} {:process 7, :type :ok, :f :append, :key "8", :value "x 7 13 y"} {:process 7, :type :invoke, :f :get, :key "4", :value nil} {:process 45, :type :ok, :f :get, :key "0", :value "x 27 6 yx 46 3 yx 25 1 yx 0 2 yx 25 4 yx 25 5 yx 20 5 yx 14 8 yx 2 1 y"} {:process 45, :type :invoke, :f :get, :key "2", :value nil} {:process 42, :type :ok, :f :get, :key "5", :value "x 7 12 y"} {:process 42, :type :invoke, :f :get, :key "7", :value nil} {:process 26, :type :ok, :f :get, :key "3", :value "x 35 13 yx 6 5 yx 3 3 yx 20 2 yx 42 2 yx 4 3 yx 42 5 yx 42 6 yx 46 5 yx 18 3 yx 45 9 y"} {:process 26, :type :invoke, :f :get, :key "9", :value nil} {:process 41, :type :ok, :f :get, :key "3", :value "x 35 13 yx 6 5 yx 3 3 yx 20 2 yx 42 2 yx 4 3 yx 42 5 yx 42 6 yx 46 5 yx 18 3 yx 45 9 y"} {:process 41, :type :invoke, :f :get, :key "4", :value nil} {:process 23, :type :ok, :f :get, :key "2", :value "x 7 10 yx 49 5 yx 23 4 yx 2 5 yx 23 5 y"} {:process 23, :type :invoke, :f :get, :key "3", :value nil} {:process 23, :type :ok, :f :get, :key "3", :value "x 35 13 yx 6 5 yx 3 3 yx 20 2 yx 42 2 yx 4 3 yx 42 5 yx 42 6 yx 46 5 yx 18 3 yx 45 9 y"} {:process 23, :type :invoke, :f :append, :key "1", :value "x 23 6 y"} {:process 45, :type :ok, :f :get, :key "2", :value "x 7 10 yx 49 5 yx 23 4 yx 2 5 yx 23 5 y"} {:process 45, :type :invoke, :f :append, :key "7", :value "x 45 10 y"} {:process 0, :type :ok, :f :append, :key "4", :value "x 0 4 y"} {:process 0, :type :invoke, :f :get, :key "0", :value nil} {:process 7, :type :ok, :f :get, :key "4", :value "x 44 1 yx 38 5 yx 15 6 yx 44 3 yx 4 0 yx 7 3 yx 46 2 yx 36 3 yx 49 2 yx 49 3 yx 39 3 yx 32 1 yx 31 5 yx 45 3 yx 32 4 yx 28 7 yx 45 6 yx 27 12 yx 0 4 y"} {:process 7, :type :invoke, :f :append, :key "5", :value "x 7 14 y"} {:process 41, :type :ok, :f :get, :key "4", :value "x 44 1 yx 38 5 yx 15 6 yx 44 3 yx 4 0 yx 7 3 yx 46 2 yx 36 3 yx 49 2 yx 49 3 yx 39 3 yx 32 1 yx 31 5 yx 45 3 yx 32 4 yx 28 7 yx 45 6 yx 27 12 yx 0 4 y"} {:process 41, :type :invoke, :f :get, :key "0", :value nil} {:process 48, :type :ok, :f :append, :key "9", :value "x 48 2 y"} {:process 48, :type :invoke, :f :append, :key "8", :value "x 48 3 y"} {:process 16, :type :ok, :f :get, :key "4", :value "x 44 1 yx 38 5 yx 15 6 yx 44 3 yx 4 0 yx 7 3 yx 46 2 yx 36 3 yx 49 2 yx 49 3 yx 39 3 yx 32 1 yx 31 5 yx 45 3 yx 32 4 yx 28 7 yx 45 6 yx 27 12 yx 0 4 y"} {:process 16, :type :invoke, :f :get, :key "7", :value nil} {:process 5, :type :ok, :f :append, :key "7", :value "x 5 1 y"} {:process 5, :type :invoke, :f :append, :key "5", :value "x 5 2 y"} {:process 5, :type :ok, :f :append, :key "5", :value "x 5 2 y"} {:process 5, :type :invoke, :f :append, :key "2", :value "x 5 3 y"} {:process 16, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 yx 4 2 yx 32 2 yx 24 3 yx 26 4 yx 6 7 yx 28 8 yx 2 3 yx 6 9 yx 45 8 yx 41 11 yx 45 10 y"} {:process 16, :type :invoke, :f :get, :key "6", :value nil} {:process 5, :type :ok, :f :append, :key "2", :value "x 5 3 y"} {:process 5, :type :invoke, :f :get, :key "2", :value nil} {:process 16, :type :ok, :f :get, :key "6", :value "x 32 3 yx 6 10 yx 7 11 y"} {:process 16, :type :invoke, :f :append, :key "6", :value "x 16 0 y"} {:process 5, :type :ok, :f :get, :key "2", :value "x 7 10 yx 49 5 yx 23 4 yx 2 5 yx 23 5 yx 5 3 y"} {:process 5, :type :invoke, :f :get, :key "2", :value nil} {:process 15, :type :ok, :f :append, :key "4", :value "x 15 8 y"} {:process 15, :type :invoke, :f :get, :key "1", :value nil} {:process 5, :type :ok, :f :get, :key "2", :value "x 7 10 yx 49 5 yx 23 4 yx 2 5 yx 23 5 yx 5 3 y"} {:process 5, :type :invoke, :f :get, :key "8", :value nil} {:process 15, :type :ok, :f :get, :key "1", :value "x 26 11 y"} {:process 15, :type :invoke, :f :get, :key "2", :value nil} {:process 16, :type :ok, :f :append, :key "6", :value "x 16 0 y"} {:process 16, :type :invoke, :f :append, :key "6", :value "x 16 1 y"} {:process 5, :type :ok, :f :get, :key "8", :value "x 14 4 yx 43 2 yx 45 1 yx 46 4 yx 27 11 yx 0 3 yx 24 2 yx 45 2 yx 13 4 yx 13 5 yx 6 8 yx 42 9 yx 7 13 yx 49 7 yx 48 3 y"} {:process 5, :type :invoke, :f :get, :key "0", :value nil} {:process 16, :type :ok, :f :append, :key "6", :value "x 16 1 y"} {:process 16, :type :invoke, :f :get, :key "8", :value nil} {:process 15, :type :ok, :f :get, :key "2", :value "x 7 10 yx 49 5 yx 23 4 yx 2 5 yx 23 5 yx 5 3 y"} {:process 15, :type :invoke, :f :put, :key "0", :value "x 15 9 y"} {:process 16, :type :ok, :f :get, :key "8", :value "x 14 4 yx 43 2 yx 45 1 yx 46 4 yx 27 11 yx 0 3 yx 24 2 yx 45 2 yx 13 4 yx 13 5 yx 6 8 yx 42 9 yx 7 13 yx 49 7 yx 48 3 y"} {:process 16, :type :invoke, :f :get, :key "5", :value nil} {:process 15, :type :ok, :f :put, :key "0", :value "x 15 9 y"} {:process 5, :type :ok, :f :get, :key "0", :value "x 27 6 yx 46 3 yx 25 1 yx 0 2 yx 25 4 yx 25 5 yx 20 5 yx 14 8 yx 2 1 y"} {:process 5, :type :invoke, :f :append, :key "3", :value "x 5 4 y"} {:process 15, :type :invoke, :f :get, :key "0", :value nil} {:process 16, :type :ok, :f :get, :key "5", :value "x 7 12 yx 5 2 y"} {:process 16, :type :invoke, :f :append, :key "2", :value "x 16 2 y"} {:process 5, :type :ok, :f :append, :key "3", :value "x 5 4 y"} {:process 5, :type :invoke, :f :get, :key "9", :value nil} {:process 16, :type :ok, :f :append, :key "2", :value "x 16 2 y"} {:process 16, :type :invoke, :f :get, :key "0", :value nil} {:process 5, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 y"} {:process 5, :type :invoke, :f :get, :key "1", :value nil} {:process 16, :type :ok, :f :get, :key "0", :value "x 15 9 y"} {:process 16, :type :invoke, :f :get, :key "9", :value nil} {:process 16, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 y"} {:process 16, :type :invoke, :f :get, :key "1", :value nil} {:process 1, :type :ok, :f :put, :key "3", :value "x 1 3 y"} {:process 1, :type :invoke, :f :append, :key "4", :value "x 1 4 y"} {:process 16, :type :ok, :f :get, :key "1", :value "x 26 11 y"} {:process 16, :type :invoke, :f :get, :key "2", :value nil} {:process 19, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 yx 4 2 yx 32 2 yx 24 3 yx 26 4 yx 6 7 yx 28 8 yx 2 3 yx 6 9 yx 45 8 yx 41 11 yx 45 10 y"} {:process 19, :type :invoke, :f :get, :key "0", :value nil} {:process 1, :type :ok, :f :append, :key "4", :value "x 1 4 y"} {:process 1, :type :invoke, :f :get, :key "7", :value nil} {:process 19, :type :ok, :f :get, :key "0", :value "x 15 9 y"} {:process 19, :type :invoke, :f :get, :key "0", :value nil} {:process 4, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 yx 4 2 yx 32 2 yx 24 3 yx 26 4 yx 6 7 yx 28 8 yx 2 3 yx 6 9 yx 45 8 yx 41 11 yx 45 10 y"} {:process 4, :type :invoke, :f :get, :key "3", :value nil} {:process 1, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 yx 4 2 yx 32 2 yx 24 3 yx 26 4 yx 6 7 yx 28 8 yx 2 3 yx 6 9 yx 45 8 yx 41 11 yx 45 10 y"} {:process 1, :type :invoke, :f :get, :key "7", :value nil} {:process 19, :type :ok, :f :get, :key "0", :value "x 15 9 y"} {:process 19, :type :invoke, :f :get, :key "0", :value nil} {:process 3, :type :ok, :f :get, :key "2", :value "x 7 10 yx 49 5 yx 23 4 yx 2 5 yx 23 5 yx 5 3 yx 16 2 y"} {:process 3, :type :invoke, :f :append, :key "8", :value "x 3 6 y"} {:process 1, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 yx 4 2 yx 32 2 yx 24 3 yx 26 4 yx 6 7 yx 28 8 yx 2 3 yx 6 9 yx 45 8 yx 41 11 yx 45 10 y"} {:process 1, :type :invoke, :f :get, :key "0", :value nil} {:process 4, :type :ok, :f :get, :key "3", :value "x 1 3 y"} {:process 4, :type :invoke, :f :get, :key "7", :value nil} {:process 17, :type :ok, :f :get, :key "1", :value "x 26 11 y"} {:process 17, :type :invoke, :f :append, :key "7", :value "x 17 3 y"} {:process 1, :type :ok, :f :get, :key "0", :value "x 15 9 y"} {:process 1, :type :invoke, :f :get, :key "0", :value nil} {:process 11, :type :ok, :f :get, :key "2", :value "x 7 10 yx 49 5 yx 23 4 yx 2 5 yx 23 5 yx 5 3 yx 16 2 y"} {:process 11, :type :invoke, :f :get, :key "5", :value nil} {:process 17, :type :ok, :f :append, :key "7", :value "x 17 3 y"} {:process 17, :type :invoke, :f :append, :key "5", :value "x 17 4 y"} {:process 17, :type :ok, :f :append, :key "5", :value "x 17 4 y"} {:process 17, :type :invoke, :f :get, :key "8", :value nil} {:process 4, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 yx 4 2 yx 32 2 yx 24 3 yx 26 4 yx 6 7 yx 28 8 yx 2 3 yx 6 9 yx 45 8 yx 41 11 yx 45 10 yx 17 3 y"} {:process 4, :type :invoke, :f :get, :key "0", :value nil} {:process 1, :type :ok, :f :get, :key "0", :value "x 15 9 y"} {:process 1, :type :invoke, :f :put, :key "4", :value "x 1 5 y"} {:process 4, :type :ok, :f :get, :key "0", :value "x 15 9 y"} {:process 4, :type :invoke, :f :append, :key "6", :value "x 4 4 y"} {:process 43, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 yx 4 2 yx 32 2 yx 24 3 yx 26 4 yx 6 7 yx 28 8 yx 2 3 yx 6 9 yx 45 8 yx 41 11 yx 45 10 yx 17 3 y"} {:process 43, :type :invoke, :f :get, :key "7", :value nil} {:process 20, :type :ok, :f :append, :key "9", :value "x 20 6 y"} {:process 20, :type :invoke, :f :append, :key "2", :value "x 20 7 y"} {:process 4, :type :ok, :f :append, :key "6", :value "x 4 4 y"} {:process 4, :type :invoke, :f :get, :key "9", :value nil} {:process 1, :type :ok, :f :put, :key "4", :value "x 1 5 y"} {:process 1, :type :invoke, :f :append, :key "9", :value "x 1 6 y"} {:process 17, :type :ok, :f :get, :key "8", :value "x 14 4 yx 43 2 yx 45 1 yx 46 4 yx 27 11 yx 0 3 yx 24 2 yx 45 2 yx 13 4 yx 13 5 yx 6 8 yx 42 9 yx 7 13 yx 49 7 yx 48 3 y"} {:process 17, :type :invoke, :f :append, :key "1", :value "x 17 5 y"} {:process 43, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 yx 4 2 yx 32 2 yx 24 3 yx 26 4 yx 6 7 yx 28 8 yx 2 3 yx 6 9 yx 45 8 yx 41 11 yx 45 10 yx 17 3 y"} {:process 43, :type :invoke, :f :append, :key "7", :value "x 43 3 y"} {:process 4, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 y"} {:process 4, :type :invoke, :f :put, :key "3", :value "x 4 5 y"} {:process 1, :type :ok, :f :append, :key "9", :value "x 1 6 y"} {:process 1, :type :invoke, :f :get, :key "2", :value nil} {:process 17, :type :ok, :f :append, :key "1", :value "x 17 5 y"} {:process 17, :type :invoke, :f :get, :key "3", :value nil} {:process 36, :type :ok, :f :append, :key "4", :value "x 36 4 y"} {:process 36, :type :invoke, :f :get, :key "9", :value nil} {:process 14, :type :ok, :f :append, :key "6", :value "x 14 9 y"} {:process 14, :type :invoke, :f :append, :key "0", :value "x 14 10 y"} {:process 32, :type :ok, :f :get, :key "6", :value "x 32 3 yx 6 10 yx 7 11 yx 16 0 yx 16 1 yx 4 4 yx 14 9 y"} {:process 32, :type :invoke, :f :get, :key "5", :value nil} {:process 36, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 y"} {:process 36, :type :invoke, :f :get, :key "0", :value nil} {:process 14, :type :ok, :f :append, :key "0", :value "x 14 10 y"} {:process 14, :type :invoke, :f :append, :key "2", :value "x 14 11 y"} {:process 13, :type :ok, :f :get, :key "0", :value "x 15 9 yx 14 10 y"} {:process 13, :type :invoke, :f :append, :key "1", :value "x 13 6 y"} {:process 32, :type :ok, :f :get, :key "5", :value "x 7 12 yx 5 2 yx 17 4 y"} {:process 32, :type :invoke, :f :append, :key "4", :value "x 32 5 y"} {:process 33, :type :ok, :f :append, :key "5", :value "x 33 2 y"} {:process 33, :type :invoke, :f :put, :key "0", :value "x 33 3 y"} {:process 14, :type :ok, :f :append, :key "2", :value "x 14 11 y"} {:process 14, :type :invoke, :f :get, :key "6", :value nil} {:process 33, :type :ok, :f :put, :key "0", :value "x 33 3 y"} {:process 33, :type :invoke, :f :append, :key "3", :value "x 33 4 y"} {:process 36, :type :ok, :f :get, :key "0", :value "x 33 3 y"} {:process 36, :type :invoke, :f :get, :key "6", :value nil} {:process 40, :type :ok, :f :get, :key "4", :value "x 1 5 yx 36 4 y"} {:process 40, :type :invoke, :f :append, :key "5", :value "x 40 10 y"} {:process 32, :type :ok, :f :append, :key "4", :value "x 32 5 y"} {:process 32, :type :invoke, :f :append, :key "3", :value "x 32 6 y"} {:process 14, :type :ok, :f :get, :key "6", :value "x 32 3 yx 6 10 yx 7 11 yx 16 0 yx 16 1 yx 4 4 yx 14 9 y"} {:process 14, :type :invoke, :f :get, :key "1", :value nil} {:process 33, :type :ok, :f :append, :key "3", :value "x 33 4 y"} {:process 33, :type :invoke, :f :append, :key "4", :value "x 33 5 y"} {:process 32, :type :ok, :f :append, :key "3", :value "x 32 6 y"} {:process 32, :type :invoke, :f :append, :key "6", :value "x 32 7 y"} {:process 40, :type :ok, :f :append, :key "5", :value "x 40 10 y"} {:process 40, :type :invoke, :f :get, :key "3", :value nil} {:process 36, :type :ok, :f :get, :key "6", :value "x 32 3 yx 6 10 yx 7 11 yx 16 0 yx 16 1 yx 4 4 yx 14 9 y"} {:process 36, :type :invoke, :f :get, :key "0", :value nil} {:process 28, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 y"} {:process 28, :type :invoke, :f :append, :key "4", :value "x 28 9 y"} {:process 14, :type :ok, :f :get, :key "1", :value "x 26 11 yx 17 5 yx 24 4 yx 13 6 y"} {:process 14, :type :invoke, :f :append, :key "6", :value "x 14 12 y"} {:process 33, :type :ok, :f :append, :key "4", :value "x 33 5 y"} {:process 33, :type :invoke, :f :get, :key "6", :value nil} {:process 34, :type :ok, :f :append, :key "6", :value "x 34 6 y"} {:process 34, :type :invoke, :f :append, :key "5", :value "x 34 7 y"} {:process 32, :type :ok, :f :append, :key "6", :value "x 32 7 y"} {:process 32, :type :invoke, :f :append, :key "8", :value "x 32 8 y"} {:process 31, :type :ok, :f :append, :key "9", :value "x 31 6 y"} {:process 31, :type :invoke, :f :put, :key "3", :value "x 31 7 y"} {:process 28, :type :ok, :f :append, :key "4", :value "x 28 9 y"} {:process 28, :type :invoke, :f :get, :key "0", :value nil} {:process 40, :type :ok, :f :get, :key "3", :value "x 1 3 yx 33 4 yx 32 6 y"} {:process 40, :type :invoke, :f :get, :key "8", :value nil} {:process 31, :type :ok, :f :put, :key "3", :value "x 31 7 y"} {:process 31, :type :invoke, :f :append, :key "4", :value "x 31 8 y"} {:process 28, :type :ok, :f :get, :key "0", :value "x 33 3 y"} {:process 28, :type :invoke, :f :append, :key "2", :value "x 28 10 y"} {:process 34, :type :ok, :f :append, :key "5", :value "x 34 7 y"} {:process 32, :type :ok, :f :append, :key "8", :value "x 32 8 y"} {:process 34, :type :invoke, :f :get, :key "2", :value nil} {:process 14, :type :ok, :f :append, :key "6", :value "x 14 12 y"} {:process 14, :type :invoke, :f :put, :key "2", :value "x 14 13 y"} {:process 32, :type :invoke, :f :append, :key "8", :value "x 32 9 y"} {:process 33, :type :ok, :f :get, :key "6", :value "x 32 3 yx 6 10 yx 7 11 yx 16 0 yx 16 1 yx 4 4 yx 14 9 yx 34 6 yx 32 7 yx 14 12 y"} {:process 33, :type :invoke, :f :get, :key "3", :value nil} {:process 46, :type :ok, :f :append, :key "9", :value "x 46 6 y"} {:process 46, :type :invoke, :f :get, :key "7", :value nil} {:process 33, :type :ok, :f :get, :key "3", :value "x 31 7 y"} {:process 33, :type :invoke, :f :append, :key "5", :value "x 33 6 y"} {:process 35, :type :ok, :f :append, :key "1", :value "x 35 15 y"} {:process 35, :type :invoke, :f :put, :key "1", :value "x 35 16 y"} {:process 40, :type :ok, :f :get, :key "8", :value "x 14 4 yx 43 2 yx 45 1 yx 46 4 yx 27 11 yx 0 3 yx 24 2 yx 45 2 yx 13 4 yx 13 5 yx 6 8 yx 42 9 yx 7 13 yx 49 7 yx 48 3 yx 32 8 y"} {:process 40, :type :invoke, :f :append, :key "4", :value "x 40 11 y"} {:process 9, :type :ok, :f :append, :key "7", :value "x 9 4 y"} {:process 9, :type :invoke, :f :get, :key "1", :value nil} {:process 28, :type :ok, :f :append, :key "2", :value "x 28 10 y"} {:process 28, :type :invoke, :f :append, :key "4", :value "x 28 11 y"} {:process 32, :type :ok, :f :append, :key "8", :value "x 32 9 y"} {:process 32, :type :invoke, :f :append, :key "3", :value "x 32 10 y"} {:process 46, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 yx 4 2 yx 32 2 yx 24 3 yx 26 4 yx 6 7 yx 28 8 yx 2 3 yx 6 9 yx 45 8 yx 41 11 yx 45 10 yx 17 3 yx 43 3 yx 9 4 y"} {:process 46, :type :invoke, :f :put, :key "8", :value "x 46 7 y"} {:process 33, :type :ok, :f :append, :key "5", :value "x 33 6 y"} {:process 33, :type :invoke, :f :append, :key "7", :value "x 33 7 y"} {:process 14, :type :ok, :f :put, :key "2", :value "x 14 13 y"} {:process 14, :type :invoke, :f :append, :key "7", :value "x 14 14 y"} {:process 9, :type :ok, :f :get, :key "1", :value "x 26 11 yx 17 5 yx 24 4 yx 13 6 yx 35 15 y"} {:process 9, :type :invoke, :f :append, :key "6", :value "x 9 5 y"} {:process 49, :type :ok, :f :append, :key "8", :value "x 49 7 y"} {:process 49, :type :invoke, :f :get, :key "0", :value nil} {:process 35, :type :ok, :f :put, :key "1", :value "x 35 16 y"} {:process 35, :type :invoke, :f :get, :key "6", :value nil} {:process 2, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 y"} {:process 2, :type :invoke, :f :get, :key "3", :value nil} {:process 32, :type :ok, :f :append, :key "3", :value "x 32 10 y"} {:process 32, :type :invoke, :f :get, :key "2", :value nil} {:process 33, :type :ok, :f :append, :key "7", :value "x 33 7 y"} {:process 33, :type :invoke, :f :get, :key "3", :value nil} {:process 9, :type :ok, :f :append, :key "6", :value "x 9 5 y"} {:process 9, :type :invoke, :f :append, :key "4", :value "x 9 6 y"} {:process 14, :type :ok, :f :append, :key "7", :value "x 14 14 y"} {:process 14, :type :invoke, :f :append, :key "6", :value "x 14 15 y"} {:process 46, :type :ok, :f :put, :key "8", :value "x 46 7 y"} {:process 46, :type :invoke, :f :get, :key "4", :value nil} {:process 18, :type :ok, :f :append, :key "3", :value "x 18 3 y"} {:process 18, :type :invoke, :f :append, :key "3", :value "x 18 4 y"} {:process 6, :type :ok, :f :get, :key "4", :value "x 1 5 yx 36 4 yx 32 5 yx 33 5 yx 28 9 yx 28 11 y"} {:process 6, :type :invoke, :f :get, :key "4", :value nil} {:process 49, :type :ok, :f :get, :key "0", :value "x 33 3 y"} {:process 49, :type :invoke, :f :append, :key "0", :value "x 49 8 y"} {:process 32, :type :ok, :f :get, :key "2", :value "x 14 13 y"} {:process 32, :type :invoke, :f :append, :key "2", :value "x 32 11 y"} {:process 35, :type :ok, :f :get, :key "6", :value "x 32 3 yx 6 10 yx 7 11 yx 16 0 yx 16 1 yx 4 4 yx 14 9 yx 34 6 yx 32 7 yx 14 12 yx 9 5 y"} {:process 35, :type :invoke, :f :get, :key "1", :value nil} {:process 26, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 y"} {:process 26, :type :invoke, :f :get, :key "1", :value nil} {:process 14, :type :ok, :f :append, :key "6", :value "x 14 15 y"} {:process 14, :type :invoke, :f :append, :key "9", :value "x 14 16 y"} {:process 18, :type :ok, :f :append, :key "3", :value "x 18 4 y"} {:process 18, :type :invoke, :f :put, :key "2", :value "x 18 5 y"} {:process 46, :type :ok, :f :get, :key "4", :value "x 1 5 yx 36 4 yx 32 5 yx 33 5 yx 28 9 yx 28 11 yx 9 6 y"} {:process 46, :type :invoke, :f :append, :key "1", :value "x 46 8 y"} {:process 6, :type :ok, :f :get, :key "4", :value "x 1 5 yx 36 4 yx 32 5 yx 33 5 yx 28 9 yx 28 11 yx 9 6 y"} {:process 35, :type :ok, :f :get, :key "1", :value "x 35 16 y"} {:process 35, :type :invoke, :f :get, :key "9", :value nil} {:process 6, :type :invoke, :f :put, :key "6", :value "x 6 11 y"} {:process 49, :type :ok, :f :append, :key "0", :value "x 49 8 y"} {:process 49, :type :invoke, :f :append, :key "8", :value "x 49 9 y"} {:process 23, :type :ok, :f :append, :key "1", :value "x 23 6 y"} {:process 7, :type :ok, :f :append, :key "5", :value "x 7 14 y"} {:process 6, :type :ok, :f :put, :key "6", :value "x 6 11 y"} {:process 25, :type :ok, :f :append, :key "0", :value "x 25 5 y"} {:process 8, :type :ok, :f :append, :key "0", :value "x 8 4 y"} {:process 39, :type :ok, :f :append, :key "6", :value "x 39 4 y"} {:process 21, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 y"} {:process 22, :type :ok, :f :append, :key "1", :value "x 22 0 y"} {:process 0, :type :ok, :f :get, :key "0", :value "x 33 3 yx 49 8 yx 8 4 y"} {:process 45, :type :ok, :f :append, :key "7", :value "x 45 10 y"} {:process 10, :type :ok, :f :append, :key "0", :value "x 10 1 y"} {:process 37, :type :ok, :f :get, :key "1", :value "x 35 16 yx 46 8 yx 23 6 y"} {:process 44, :type :ok, :f :get, :key "5", :value "x 7 12 yx 5 2 yx 17 4 yx 40 10 yx 34 7 yx 33 6 yx 7 14 y"} {:process 48, :type :ok, :f :append, :key "8", :value "x 48 3 y"} {:process 29, :type :ok, :f :append, :key "2", :value "x 29 4 y"} {:process 15, :type :ok, :f :get, :key "0", :value "x 33 3 yx 49 8 yx 8 4 yx 10 1 y"} {:process 5, :type :ok, :f :get, :key "1", :value "x 35 16 yx 46 8 yx 23 6 y"} {:process 19, :type :ok, :f :get, :key "0", :value "x 33 3 yx 49 8 yx 8 4 yx 10 1 y"} {:process 17, :type :ok, :f :get, :key "3", :value "x 31 7 yx 32 10 yx 18 4 y"} {:process 4, :type :ok, :f :put, :key "3", :value "x 4 5 y"} {:process 20, :type :ok, :f :append, :key "2", :value "x 20 7 y"} {:process 31, :type :ok, :f :append, :key "4", :value "x 31 8 y"} {:process 24, :type :ok, :f :append, :key "1", :value "x 24 4 y"} {:process 13, :type :ok, :f :append, :key "1", :value "x 13 6 y"} {:process 34, :type :ok, :f :get, :key "2", :value "x 14 13 yx 32 11 y"} {:process 36, :type :ok, :f :get, :key "0", :value "x 33 3 yx 49 8 yx 8 4 yx 10 1 y"} {:process 28, :type :ok, :f :append, :key "4", :value "x 28 11 y"} {:process 2, :type :ok, :f :get, :key "3", :value "x 4 5 y"} {:process 26, :type :ok, :f :get, :key "1", :value "x 35 16 yx 46 8 yx 23 6 y"} {:process 35, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 y"} {:process 49, :type :ok, :f :append, :key "8", :value "x 49 9 y"} {:process 9, :type :ok, :f :append, :key "4", :value "x 9 6 y"} {:process 40, :type :ok, :f :append, :key "4", :value "x 40 11 y"} {:process 18, :type :ok, :f :put, :key "2", :value "x 18 5 y"} {:process 38, :type :ok, :f :append, :key "1", :value "x 38 8 y"} {:process 14, :type :ok, :f :append, :key "9", :value "x 14 16 y"} {:process 30, :type :ok, :f :get, :key "0", :value "x 33 3 yx 49 8 yx 8 4 yx 10 1 y"} {:process 46, :type :ok, :f :append, :key "1", :value "x 46 8 y"} {:process 33, :type :ok, :f :get, :key "3", :value "x 4 5 y"} {:process 41, :type :ok, :f :get, :key "0", :value "x 33 3 yx 49 8 yx 8 4 yx 10 1 y"} {:process 47, :type :ok, :f :append, :key "8", :value "x 47 1 y"} {:process 12, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 yx 4 2 yx 32 2 yx 24 3 yx 26 4 yx 6 7 yx 28 8 yx 2 3 yx 6 9 yx 45 8 yx 41 11 yx 45 10 yx 17 3 yx 43 3 yx 9 4 yx 33 7 yx 14 14 y"} {:process 11, :type :ok, :f :get, :key "5", :value "x 7 12 yx 5 2 yx 17 4 yx 40 10 yx 34 7 yx 33 6 yx 7 14 y"} {:process 3, :type :ok, :f :append, :key "8", :value "x 3 6 y"} {:process 16, :type :ok, :f :get, :key "2", :value "x 18 5 y"} {:process 1, :type :ok, :f :get, :key "2", :value "x 18 5 y"} {:process 43, :type :ok, :f :append, :key "7", :value "x 43 3 y"} {:process 27, :type :ok, :f :get, :key "6", :value "x 6 11 y"} {:process 42, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 yx 4 2 yx 32 2 yx 24 3 yx 26 4 yx 6 7 yx 28 8 yx 2 3 yx 6 9 yx 45 8 yx 41 11 yx 45 10 yx 17 3 yx 43 3 yx 9 4 yx 33 7 yx 14 14 y"} {:process 32, :type :ok, :f :append, :key "2", :value "x 32 11 y"} {:process 9, :type :invoke, :f :append, :key "7", :value "x 9 0 y"} {:process 0, :type :invoke, :f :get, :key "7", :value nil} {:process 1, :type :invoke, :f :get, :key "8", :value nil} {:process 2, :type :invoke, :f :get, :key "5", :value nil} {:process 3, :type :invoke, :f :put, :key "8", :value "x 3 0 y"} {:process 4, :type :invoke, :f :append, :key "2", :value "x 4 0 y"} {:process 5, :type :invoke, :f :get, :key "8", :value nil} {:process 6, :type :invoke, :f :append, :key "3", :value "x 6 0 y"} {:process 7, :type :invoke, :f :get, :key "6", :value nil} {:process 8, :type :invoke, :f :get, :key "4", :value nil} {:process 22, :type :invoke, :f :get, :key "2", :value nil} {:process 10, :type :invoke, :f :get, :key "7", :value nil} {:process 11, :type :invoke, :f :append, :key "4", :value "x 11 0 y"} {:process 12, :type :invoke, :f :get, :key "3", :value nil} {:process 13, :type :invoke, :f :append, :key "9", :value "x 13 0 y"} {:process 14, :type :invoke, :f :append, :key "1", :value "x 14 0 y"} {:process 15, :type :invoke, :f :append, :key "6", :value "x 15 0 y"} {:process 16, :type :invoke, :f :append, :key "2", :value "x 16 0 y"} {:process 17, :type :invoke, :f :append, :key "7", :value "x 17 0 y"} {:process 18, :type :invoke, :f :append, :key "7", :value "x 18 0 y"} {:process 19, :type :invoke, :f :append, :key "7", :value "x 19 0 y"} {:process 20, :type :invoke, :f :append, :key "3", :value "x 20 0 y"} {:process 49, :type :invoke, :f :append, :key "1", :value "x 49 0 y"} {:process 21, :type :invoke, :f :append, :key "3", :value "x 21 0 y"} {:process 23, :type :invoke, :f :get, :key "7", :value nil} {:process 36, :type :invoke, :f :append, :key "2", :value "x 36 0 y"} {:process 37, :type :invoke, :f :get, :key "4", :value nil} {:process 24, :type :invoke, :f :append, :key "1", :value "x 24 0 y"} {:process 38, :type :invoke, :f :get, :key "4", :value nil} {:process 25, :type :invoke, :f :get, :key "4", :value nil} {:process 39, :type :invoke, :f :put, :key "0", :value "x 39 0 y"} {:process 26, :type :invoke, :f :get, :key "5", :value nil} {:process 27, :type :invoke, :f :append, :key "3", :value "x 27 0 y"} {:process 40, :type :invoke, :f :get, :key "9", :value nil} {:process 41, :type :invoke, :f :get, :key "1", :value nil} {:process 28, :type :invoke, :f :get, :key "2", :value nil} {:process 42, :type :invoke, :f :get, :key "7", :value nil} {:process 29, :type :invoke, :f :get, :key "0", :value nil} {:process 30, :type :invoke, :f :append, :key "8", :value "x 30 0 y"} {:process 43, :type :invoke, :f :get, :key "2", :value nil} {:process 31, :type :invoke, :f :get, :key "7", :value nil} {:process 32, :type :invoke, :f :get, :key "8", :value nil} {:process 44, :type :invoke, :f :get, :key "5", :value nil} {:process 33, :type :invoke, :f :get, :key "9", :value nil} {:process 45, :type :invoke, :f :get, :key "9", :value nil} {:process 34, :type :invoke, :f :get, :key "8", :value nil} {:process 46, :type :invoke, :f :get, :key "9", :value nil} {:process 35, :type :invoke, :f :get, :key "3", :value nil} {:process 47, :type :invoke, :f :get, :key "0", :value nil} {:process 48, :type :invoke, :f :append, :key "1", :value "x 48 0 y"} {:process 1, :type :ok, :f :get, :key "8", :value "x 46 7 yx 49 9 yx 3 6 y"} {:process 1, :type :invoke, :f :get, :key "9", :value nil} {:process 39, :type :ok, :f :put, :key "0", :value "x 39 0 y"} {:process 39, :type :invoke, :f :append, :key "6", :value "x 39 1 y"} {:process 24, :type :ok, :f :append, :key "1", :value "x 24 0 y"} {:process 24, :type :invoke, :f :append, :key "8", :value "x 24 1 y"} {:process 32, :type :ok, :f :get, :key "8", :value "x 46 7 yx 49 9 yx 3 6 y"} {:process 32, :type :invoke, :f :get, :key "3", :value nil} {:process 1, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 y"} {:process 1, :type :invoke, :f :append, :key "7", :value "x 1 0 y"} {:process 39, :type :ok, :f :append, :key "6", :value "x 39 1 y"} {:process 39, :type :invoke, :f :get, :key "7", :value nil} {:process 24, :type :ok, :f :append, :key "8", :value "x 24 1 y"} {:process 24, :type :invoke, :f :append, :key "0", :value "x 24 2 y"} {:process 32, :type :ok, :f :get, :key "3", :value "x 4 5 y"} {:process 32, :type :invoke, :f :append, :key "6", :value "x 32 0 y"} {:process 1, :type :ok, :f :append, :key "7", :value "x 1 0 y"} {:process 1, :type :invoke, :f :append, :key "8", :value "x 1 1 y"} {:process 32, :type :ok, :f :append, :key "6", :value "x 32 0 y"} {:process 32, :type :invoke, :f :get, :key "8", :value nil} {:process 24, :type :ok, :f :append, :key "0", :value "x 24 2 y"} {:process 24, :type :invoke, :f :get, :key "8", :value nil} {:process 1, :type :ok, :f :append, :key "8", :value "x 1 1 y"} {:process 1, :type :invoke, :f :get, :key "6", :value nil} {:process 32, :type :ok, :f :get, :key "8", :value "x 46 7 yx 49 9 yx 3 6 yx 24 1 yx 1 1 y"} {:process 32, :type :invoke, :f :append, :key "2", :value "x 32 1 y"} {:process 24, :type :ok, :f :get, :key "8", :value "x 46 7 yx 49 9 yx 3 6 yx 24 1 yx 1 1 y"} {:process 24, :type :invoke, :f :append, :key "6", :value "x 24 3 y"} {:process 34, :type :ok, :f :get, :key "8", :value "x 46 7 yx 49 9 yx 3 6 yx 24 1 yx 1 1 yx 30 0 y"} {:process 34, :type :invoke, :f :append, :key "1", :value "x 34 0 y"} {:process 30, :type :ok, :f :append, :key "8", :value "x 30 0 y"} {:process 30, :type :invoke, :f :append, :key "7", :value "x 30 1 y"} {:process 32, :type :ok, :f :append, :key "2", :value "x 32 1 y"} {:process 32, :type :invoke, :f :get, :key "8", :value nil} {:process 15, :type :ok, :f :append, :key "6", :value "x 15 0 y"} {:process 15, :type :invoke, :f :get, :key "8", :value nil} {:process 48, :type :ok, :f :append, :key "1", :value "x 48 0 y"} {:process 48, :type :invoke, :f :append, :key "6", :value "x 48 1 y"} {:process 30, :type :ok, :f :append, :key "7", :value "x 30 1 y"} {:process 30, :type :invoke, :f :get, :key "3", :value nil} {:process 34, :type :ok, :f :append, :key "1", :value "x 34 0 y"} {:process 34, :type :invoke, :f :append, :key "3", :value "x 34 1 y"} {:process 35, :type :ok, :f :get, :key "3", :value "x 4 5 y"} {:process 15, :type :ok, :f :get, :key "8", :value "x 46 7 yx 49 9 yx 3 6 yx 24 1 yx 1 1 yx 30 0 y"} {:process 35, :type :invoke, :f :get, :key "2", :value nil} {:process 15, :type :invoke, :f :append, :key "0", :value "x 15 1 y"} {:process 23, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 yx 4 2 yx 32 2 yx 24 3 yx 26 4 yx 6 7 yx 28 8 yx 2 3 yx 6 9 yx 45 8 yx 41 11 yx 45 10 yx 17 3 yx 43 3 yx 9 4 yx 33 7 yx 14 14 yx 1 0 yx 30 1 y"} {:process 23, :type :invoke, :f :get, :key "0", :value nil} {:process 24, :type :ok, :f :append, :key "6", :value "x 24 3 y"} {:process 24, :type :invoke, :f :get, :key "1", :value nil} {:process 23, :type :ok, :f :get, :key "0", :value "x 39 0 yx 24 2 y"} {:process 23, :type :invoke, :f :get, :key "8", :value nil} {:process 28, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 y"} {:process 28, :type :invoke, :f :get, :key "4", :value nil} {:process 34, :type :ok, :f :append, :key "3", :value "x 34 1 y"} {:process 34, :type :invoke, :f :get, :key "3", :value nil} {:process 30, :type :ok, :f :get, :key "3", :value "x 4 5 yx 34 1 y"} {:process 30, :type :invoke, :f :append, :key "9", :value "x 30 2 y"} {:process 15, :type :ok, :f :append, :key "0", :value "x 15 1 y"} {:process 15, :type :invoke, :f :append, :key "5", :value "x 15 2 y"} {:process 24, :type :ok, :f :get, :key "1", :value "x 35 16 yx 46 8 yx 23 6 yx 24 0 yx 48 0 yx 34 0 y"} {:process 24, :type :invoke, :f :append, :key "0", :value "x 24 4 y"} {:process 28, :type :ok, :f :get, :key "4", :value "x 1 5 yx 36 4 yx 32 5 yx 33 5 yx 28 9 yx 28 11 yx 9 6 yx 31 8 yx 40 11 y"} {:process 28, :type :invoke, :f :append, :key "1", :value "x 28 0 y"} {:process 15, :type :ok, :f :append, :key "5", :value "x 15 2 y"} {:process 15, :type :invoke, :f :append, :key "8", :value "x 15 3 y"} {:process 24, :type :ok, :f :append, :key "0", :value "x 24 4 y"} {:process 24, :type :invoke, :f :append, :key "2", :value "x 24 5 y"} {:process 28, :type :ok, :f :append, :key "1", :value "x 28 0 y"} {:process 28, :type :invoke, :f :append, :key "2", :value "x 28 1 y"} {:process 24, :type :ok, :f :append, :key "2", :value "x 24 5 y"} {:process 24, :type :invoke, :f :get, :key "4", :value nil} {:process 7, :type :ok, :f :get, :key "6", :value "x 6 11 yx 39 1 yx 32 0 yx 15 0 yx 24 3 y"} {:process 7, :type :invoke, :f :append, :key "8", :value "x 7 0 y"} {:process 28, :type :ok, :f :append, :key "2", :value "x 28 1 y"} {:process 28, :type :invoke, :f :get, :key "6", :value nil} {:process 12, :type :ok, :f :get, :key "3", :value "x 4 5 yx 34 1 y"} {:process 12, :type :invoke, :f :append, :key "0", :value "x 12 0 y"} {:process 15, :type :ok, :f :append, :key "8", :value "x 15 3 y"} {:process 15, :type :invoke, :f :append, :key "6", :value "x 15 4 y"} {:process 21, :type :ok, :f :append, :key "3", :value "x 21 0 y"} {:process 21, :type :invoke, :f :append, :key "0", :value "x 21 1 y"} {:process 12, :type :ok, :f :append, :key "0", :value "x 12 0 y"} {:process 12, :type :invoke, :f :get, :key "7", :value nil} {:process 22, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 y"} {:process 22, :type :invoke, :f :append, :key "8", :value "x 22 0 y"} {:process 49, :type :ok, :f :append, :key "1", :value "x 49 0 y"} {:process 49, :type :invoke, :f :get, :key "1", :value nil} {:process 15, :type :ok, :f :append, :key "6", :value "x 15 4 y"} {:process 15, :type :invoke, :f :put, :key "5", :value "x 15 5 y"} {:process 24, :type :ok, :f :get, :key "4", :value "x 1 5 yx 36 4 yx 32 5 yx 33 5 yx 28 9 yx 28 11 yx 9 6 yx 31 8 yx 40 11 y"} {:process 24, :type :invoke, :f :append, :key "9", :value "x 24 6 y"} {:process 44, :type :ok, :f :get, :key "5", :value "x 7 12 yx 5 2 yx 17 4 yx 40 10 yx 34 7 yx 33 6 yx 7 14 yx 15 2 y"} {:process 44, :type :invoke, :f :put, :key "6", :value "x 44 0 y"} {:process 21, :type :ok, :f :append, :key "0", :value "x 21 1 y"} {:process 21, :type :invoke, :f :append, :key "3", :value "x 21 2 y"} {:process 9, :type :ok, :f :append, :key "7", :value "x 9 0 y"} {:process 9, :type :invoke, :f :get, :key "0", :value nil} {:process 12, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 yx 4 2 yx 32 2 yx 24 3 yx 26 4 yx 6 7 yx 28 8 yx 2 3 yx 6 9 yx 45 8 yx 41 11 yx 45 10 yx 17 3 yx 43 3 yx 9 4 yx 33 7 yx 14 14 yx 1 0 yx 30 1 yx 9 0 y"} {:process 12, :type :invoke, :f :get, :key "0", :value nil} {:process 49, :type :ok, :f :get, :key "1", :value "x 35 16 yx 46 8 yx 23 6 yx 24 0 yx 48 0 yx 34 0 yx 28 0 yx 49 0 y"} {:process 49, :type :invoke, :f :get, :key "7", :value nil} {:process 24, :type :ok, :f :append, :key "9", :value "x 24 6 y"} {:process 24, :type :invoke, :f :get, :key "3", :value nil} {:process 15, :type :ok, :f :put, :key "5", :value "x 15 5 y"} {:process 15, :type :invoke, :f :get, :key "1", :value nil} {:process 21, :type :ok, :f :append, :key "3", :value "x 21 2 y"} {:process 22, :type :ok, :f :append, :key "8", :value "x 22 0 y"} {:process 21, :type :invoke, :f :append, :key "9", :value "x 21 3 y"} {:process 22, :type :invoke, :f :append, :key "8", :value "x 22 1 y"} {:process 24, :type :ok, :f :get, :key "3", :value "x 4 5 yx 34 1 yx 21 0 yx 21 2 y"} {:process 24, :type :invoke, :f :get, :key "1", :value nil} {:process 44, :type :ok, :f :put, :key "6", :value "x 44 0 y"} {:process 44, :type :invoke, :f :append, :key "2", :value "x 44 1 y"} {:process 9, :type :ok, :f :get, :key "0", :value "x 39 0 yx 24 2 yx 15 1 yx 24 4 yx 12 0 yx 21 1 y"} {:process 9, :type :invoke, :f :append, :key "0", :value "x 9 1 y"} {:process 24, :type :ok, :f :get, :key "1", :value "x 35 16 yx 46 8 yx 23 6 yx 24 0 yx 48 0 yx 34 0 yx 28 0 yx 49 0 y"} {:process 24, :type :invoke, :f :append, :key "6", :value "x 24 7 y"} {:process 49, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 yx 4 2 yx 32 2 yx 24 3 yx 26 4 yx 6 7 yx 28 8 yx 2 3 yx 6 9 yx 45 8 yx 41 11 yx 45 10 yx 17 3 yx 43 3 yx 9 4 yx 33 7 yx 14 14 yx 1 0 yx 30 1 yx 9 0 y"} {:process 49, :type :invoke, :f :append, :key "2", :value "x 49 1 y"} {:process 44, :type :ok, :f :append, :key "2", :value "x 44 1 y"} {:process 44, :type :invoke, :f :get, :key "5", :value nil} {:process 15, :type :ok, :f :get, :key "1", :value "x 35 16 yx 46 8 yx 23 6 yx 24 0 yx 48 0 yx 34 0 yx 28 0 yx 49 0 y"} {:process 15, :type :invoke, :f :put, :key "5", :value "x 15 6 y"} {:process 24, :type :ok, :f :append, :key "6", :value "x 24 7 y"} {:process 24, :type :invoke, :f :get, :key "2", :value nil} {:process 22, :type :ok, :f :append, :key "8", :value "x 22 1 y"} {:process 22, :type :invoke, :f :get, :key "2", :value nil} {:process 49, :type :ok, :f :append, :key "2", :value "x 49 1 y"} {:process 49, :type :invoke, :f :get, :key "3", :value nil} {:process 15, :type :ok, :f :put, :key "5", :value "x 15 6 y"} {:process 15, :type :invoke, :f :get, :key "3", :value nil} {:process 44, :type :ok, :f :get, :key "5", :value "x 15 5 y"} {:process 44, :type :invoke, :f :append, :key "6", :value "x 44 2 y"} {:process 3, :type :ok, :f :put, :key "8", :value "x 3 0 y"} {:process 3, :type :invoke, :f :append, :key "7", :value "x 3 1 y"} {:process 5, :type :ok, :f :get, :key "8", :value "x 3 0 y"} {:process 5, :type :invoke, :f :get, :key "8", :value nil} {:process 15, :type :ok, :f :get, :key "3", :value "x 4 5 yx 34 1 yx 21 0 yx 21 2 y"} {:process 15, :type :invoke, :f :get, :key "6", :value nil} {:process 22, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 y"} {:process 22, :type :invoke, :f :get, :key "9", :value nil} {:process 44, :type :ok, :f :append, :key "6", :value "x 44 2 y"} {:process 44, :type :invoke, :f :append, :key "5", :value "x 44 3 y"} {:process 37, :type :ok, :f :get, :key "4", :value "x 1 5 yx 36 4 yx 32 5 yx 33 5 yx 28 9 yx 28 11 yx 9 6 yx 31 8 yx 40 11 y"} {:process 37, :type :invoke, :f :get, :key "6", :value nil} {:process 49, :type :ok, :f :get, :key "3", :value "x 4 5 yx 34 1 yx 21 0 yx 21 2 y"} {:process 49, :type :invoke, :f :append, :key "6", :value "x 49 2 y"} {:process 40, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 y"} {:process 40, :type :invoke, :f :append, :key "1", :value "x 40 0 y"} {:process 15, :type :ok, :f :get, :key "6", :value "x 44 0 yx 24 7 yx 44 2 y"} {:process 15, :type :invoke, :f :get, :key "6", :value nil} {:process 44, :type :ok, :f :append, :key "5", :value "x 44 3 y"} {:process 44, :type :invoke, :f :get, :key "7", :value nil} {:process 37, :type :ok, :f :get, :key "6", :value "x 44 0 yx 24 7 yx 44 2 y"} {:process 37, :type :invoke, :f :put, :key "4", :value "x 37 0 y"} {:process 5, :type :ok, :f :get, :key "8", :value "x 3 0 y"} {:process 5, :type :invoke, :f :get, :key "7", :value nil} {:process 3, :type :ok, :f :append, :key "7", :value "x 3 1 y"} {:process 3, :type :invoke, :f :append, :key "3", :value "x 3 2 y"} {:process 49, :type :ok, :f :append, :key "6", :value "x 49 2 y"} {:process 49, :type :invoke, :f :get, :key "9", :value nil} {:process 37, :type :ok, :f :put, :key "4", :value "x 37 0 y"} {:process 37, :type :invoke, :f :get, :key "6", :value nil} {:process 44, :type :ok, :f :get, :key "7", :value "x 26 0 yx 25 0 yx 34 4 yx 27 7 yx 41 10 yx 9 3 yx 27 9 yx 49 4 yx 27 10 yx 4 2 yx 32 2 yx 24 3 yx 26 4 yx 6 7 yx 28 8 yx 2 3 yx 6 9 yx 45 8 yx 41 11 yx 45 10 yx 17 3 yx 43 3 yx 9 4 yx 33 7 yx 14 14 yx 1 0 yx 30 1 yx 9 0 yx 3 1 y"} {:process 44, :type :invoke, :f :append, :key "8", :value "x 44 4 y"} {:process 22, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 y"} {:process 22, :type :invoke, :f :append, :key "2", :value "x 22 2 y"} {:process 44, :type :ok, :f :append, :key "8", :value "x 44 4 y"} {:process 44, :type :invoke, :f :put, :key "7", :value "x 44 5 y"} {:process 15, :type :ok, :f :get, :key "6", :value "x 44 0 yx 24 7 yx 44 2 yx 49 2 y"} {:process 15, :type :invoke, :f :append, :key "0", :value "x 15 7 y"} {:process 44, :type :ok, :f :put, :key "7", :value "x 44 5 y"} {:process 44, :type :invoke, :f :append, :key "1", :value "x 44 6 y"} {:process 37, :type :ok, :f :get, :key "6", :value "x 44 0 yx 24 7 yx 44 2 yx 49 2 y"} {:process 49, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 y"} {:process 37, :type :invoke, :f :get, :key "1", :value nil} {:process 49, :type :invoke, :f :append, :key "1", :value "x 49 3 y"} {:process 15, :type :ok, :f :append, :key "0", :value "x 15 7 y"} {:process 15, :type :invoke, :f :append, :key "3", :value "x 15 8 y"} {:process 37, :type :ok, :f :get, :key "1", :value "x 35 16 yx 46 8 yx 23 6 yx 24 0 yx 48 0 yx 34 0 yx 28 0 yx 49 0 y"} {:process 37, :type :invoke, :f :get, :key "4", :value nil} {:process 44, :type :ok, :f :append, :key "1", :value "x 44 6 y"} {:process 44, :type :invoke, :f :get, :key "9", :value nil} {:process 37, :type :ok, :f :get, :key "4", :value "x 37 0 y"} {:process 37, :type :invoke, :f :get, :key "0", :value nil} {:process 15, :type :ok, :f :append, :key "3", :value "x 15 8 y"} {:process 15, :type :invoke, :f :get, :key "9", :value nil} {:process 44, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 y"} {:process 44, :type :invoke, :f :append, :key "6", :value "x 44 7 y"} {:process 37, :type :ok, :f :get, :key "0", :value "x 39 0 yx 24 2 yx 15 1 yx 24 4 yx 12 0 yx 21 1 yx 15 7 y"} {:process 37, :type :invoke, :f :append, :key "7", :value "x 37 1 y"} {:process 44, :type :ok, :f :append, :key "6", :value "x 44 7 y"} {:process 44, :type :invoke, :f :append, :key "7", :value "x 44 8 y"} {:process 15, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 y"} {:process 15, :type :invoke, :f :get, :key "8", :value nil} {:process 10, :type :ok, :f :get, :key "7", :value "x 44 5 y"} {:process 10, :type :invoke, :f :get, :key "1", :value nil} {:process 44, :type :ok, :f :append, :key "7", :value "x 44 8 y"} {:process 44, :type :invoke, :f :append, :key "2", :value "x 44 9 y"} {:process 31, :type :ok, :f :get, :key "7", :value "x 44 5 yx 44 8 y"} {:process 31, :type :invoke, :f :append, :key "3", :value "x 31 0 y"} {:process 37, :type :ok, :f :append, :key "7", :value "x 37 1 y"} {:process 37, :type :invoke, :f :append, :key "1", :value "x 37 2 y"} {:process 10, :type :ok, :f :get, :key "1", :value "x 35 16 yx 46 8 yx 23 6 yx 24 0 yx 48 0 yx 34 0 yx 28 0 yx 49 0 yx 49 3 yx 44 6 y"} {:process 10, :type :invoke, :f :append, :key "8", :value "x 10 0 y"} {:process 44, :type :ok, :f :append, :key "2", :value "x 44 9 y"} {:process 44, :type :invoke, :f :append, :key "3", :value "x 44 10 y"} {:process 10, :type :ok, :f :append, :key "8", :value "x 10 0 y"} {:process 10, :type :invoke, :f :put, :key "8", :value "x 10 1 y"} {:process 44, :type :ok, :f :append, :key "3", :value "x 44 10 y"} {:process 44, :type :invoke, :f :get, :key "3", :value nil} {:process 10, :type :ok, :f :put, :key "8", :value "x 10 1 y"} {:process 10, :type :invoke, :f :append, :key "8", :value "x 10 2 y"} {:process 44, :type :ok, :f :get, :key "3", :value "x 4 5 yx 34 1 yx 21 0 yx 21 2 yx 3 2 yx 15 8 yx 44 10 y"} {:process 44, :type :invoke, :f :get, :key "1", :value nil} {:process 20, :type :ok, :f :append, :key "3", :value "x 20 0 y"} {:process 20, :type :invoke, :f :get, :key "7", :value nil} {:process 17, :type :ok, :f :append, :key "7", :value "x 17 0 y"} {:process 17, :type :invoke, :f :get, :key "2", :value nil} {:process 41, :type :ok, :f :get, :key "1", :value "x 35 16 yx 46 8 yx 23 6 yx 24 0 yx 48 0 yx 34 0 yx 28 0 yx 49 0 yx 49 3 yx 44 6 y"} {:process 41, :type :invoke, :f :append, :key "5", :value "x 41 0 y"} {:process 20, :type :ok, :f :get, :key "7", :value "x 44 5 yx 44 8 yx 37 1 yx 17 0 y"} {:process 20, :type :invoke, :f :append, :key "3", :value "x 20 1 y"} {:process 44, :type :ok, :f :get, :key "1", :value "x 35 16 yx 46 8 yx 23 6 yx 24 0 yx 48 0 yx 34 0 yx 28 0 yx 49 0 yx 49 3 yx 44 6 y"} {:process 44, :type :invoke, :f :get, :key "1", :value nil} {:process 36, :type :ok, :f :append, :key "2", :value "x 36 0 y"} {:process 36, :type :invoke, :f :get, :key "3", :value nil} {:process 42, :type :ok, :f :get, :key "7", :value "x 44 5 yx 44 8 yx 37 1 yx 17 0 y"} {:process 42, :type :invoke, :f :append, :key "4", :value "x 42 0 y"} {:process 17, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 y"} {:process 17, :type :invoke, :f :get, :key "9", :value nil} {:process 41, :type :ok, :f :append, :key "5", :value "x 41 0 y"} {:process 36, :type :ok, :f :get, :key "3", :value "x 4 5 yx 34 1 yx 21 0 yx 21 2 yx 3 2 yx 15 8 yx 44 10 yx 20 0 yx 27 0 y"} {:process 41, :type :invoke, :f :append, :key "0", :value "x 41 1 y"} {:process 36, :type :invoke, :f :append, :key "6", :value "x 36 1 y"} {:process 44, :type :ok, :f :get, :key "1", :value "x 35 16 yx 46 8 yx 23 6 yx 24 0 yx 48 0 yx 34 0 yx 28 0 yx 49 0 yx 49 3 yx 44 6 y"} {:process 44, :type :invoke, :f :get, :key "2", :value nil} {:process 41, :type :ok, :f :append, :key "0", :value "x 41 1 y"} {:process 41, :type :invoke, :f :append, :key "9", :value "x 41 2 y"} {:process 17, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 y"} {:process 42, :type :ok, :f :append, :key "4", :value "x 42 0 y"} {:process 17, :type :invoke, :f :get, :key "1", :value nil} {:process 42, :type :invoke, :f :append, :key "3", :value "x 42 1 y"} {:process 36, :type :ok, :f :append, :key "6", :value "x 36 1 y"} {:process 36, :type :invoke, :f :append, :key "4", :value "x 36 2 y"} {:process 17, :type :ok, :f :get, :key "1", :value "x 35 16 yx 46 8 yx 23 6 yx 24 0 yx 48 0 yx 34 0 yx 28 0 yx 49 0 yx 49 3 yx 44 6 y"} {:process 17, :type :invoke, :f :get, :key "4", :value nil} {:process 41, :type :ok, :f :append, :key "9", :value "x 41 2 y"} {:process 41, :type :invoke, :f :append, :key "1", :value "x 41 3 y"} {:process 4, :type :ok, :f :append, :key "2", :value "x 4 0 y"} {:process 4, :type :invoke, :f :append, :key "7", :value "x 4 1 y"} {:process 36, :type :ok, :f :append, :key "4", :value "x 36 2 y"} {:process 36, :type :invoke, :f :append, :key "1", :value "x 36 3 y"} {:process 42, :type :ok, :f :append, :key "3", :value "x 42 1 y"} {:process 42, :type :invoke, :f :append, :key "1", :value "x 42 2 y"} {:process 4, :type :ok, :f :append, :key "7", :value "x 4 1 y"} {:process 4, :type :invoke, :f :get, :key "0", :value nil} {:process 36, :type :ok, :f :append, :key "1", :value "x 36 3 y"} {:process 36, :type :invoke, :f :append, :key "0", :value "x 36 4 y"} {:process 41, :type :ok, :f :append, :key "1", :value "x 41 3 y"} {:process 41, :type :invoke, :f :append, :key "3", :value "x 41 4 y"} {:process 19, :type :ok, :f :append, :key "7", :value "x 19 0 y"} {:process 19, :type :invoke, :f :append, :key "4", :value "x 19 1 y"} {:process 17, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 y"} {:process 17, :type :invoke, :f :append, :key "6", :value "x 17 1 y"} {:process 4, :type :ok, :f :get, :key "0", :value "x 39 0 yx 24 2 yx 15 1 yx 24 4 yx 12 0 yx 21 1 yx 15 7 yx 41 1 y"} {:process 4, :type :invoke, :f :append, :key "6", :value "x 4 2 y"} {:process 36, :type :ok, :f :append, :key "0", :value "x 36 4 y"} {:process 36, :type :invoke, :f :get, :key "0", :value nil} {:process 38, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 y"} {:process 38, :type :invoke, :f :get, :key "0", :value nil} {:process 41, :type :ok, :f :append, :key "3", :value "x 41 4 y"} {:process 41, :type :invoke, :f :append, :key "2", :value "x 41 5 y"} {:process 8, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 y"} {:process 8, :type :invoke, :f :put, :key "7", :value "x 8 0 y"} {:process 17, :type :ok, :f :append, :key "6", :value "x 17 1 y"} {:process 17, :type :invoke, :f :append, :key "2", :value "x 17 2 y"} {:process 36, :type :ok, :f :get, :key "0", :value "x 39 0 yx 24 2 yx 15 1 yx 24 4 yx 12 0 yx 21 1 yx 15 7 yx 41 1 yx 36 4 y"} {:process 36, :type :invoke, :f :append, :key "1", :value "x 36 5 y"} {:process 41, :type :ok, :f :append, :key "2", :value "x 41 5 y"} {:process 41, :type :invoke, :f :get, :key "8", :value nil} {:process 8, :type :ok, :f :put, :key "7", :value "x 8 0 y"} {:process 8, :type :invoke, :f :get, :key "9", :value nil} {:process 36, :type :ok, :f :append, :key "1", :value "x 36 5 y"} {:process 36, :type :invoke, :f :append, :key "2", :value "x 36 6 y"} {:process 36, :type :ok, :f :append, :key "2", :value "x 36 6 y"} {:process 36, :type :invoke, :f :append, :key "5", :value "x 36 7 y"} {:process 41, :type :ok, :f :get, :key "8", :value "x 10 1 y"} {:process 41, :type :invoke, :f :get, :key "1", :value nil} {:process 17, :type :ok, :f :append, :key "2", :value "x 17 2 y"} {:process 17, :type :invoke, :f :append, :key "5", :value "x 17 3 y"} {:process 8, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 y"} {:process 8, :type :invoke, :f :get, :key "1", :value nil} {:process 17, :type :ok, :f :append, :key "5", :value "x 17 3 y"} {:process 17, :type :invoke, :f :get, :key "6", :value nil} {:process 46, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 y"} {:process 46, :type :invoke, :f :append, :key "1", :value "x 46 0 y"} {:process 8, :type :ok, :f :get, :key "1", :value "x 35 16 yx 46 8 yx 23 6 yx 24 0 yx 48 0 yx 34 0 yx 28 0 yx 49 0 yx 49 3 yx 44 6 yx 36 3 yx 41 3 yx 36 5 y"} {:process 8, :type :invoke, :f :get, :key "8", :value nil} {:process 14, :type :ok, :f :append, :key "1", :value "x 14 0 y"} {:process 14, :type :invoke, :f :get, :key "7", :value nil} {:process 2, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 y"} {:process 2, :type :invoke, :f :append, :key "6", :value "x 2 0 y"} {:process 47, :type :ok, :f :get, :key "0", :value "x 39 0 yx 24 2 yx 15 1 yx 24 4 yx 12 0 yx 21 1 yx 15 7 yx 41 1 yx 36 4 y"} {:process 47, :type :invoke, :f :get, :key "1", :value nil} {:process 17, :type :ok, :f :get, :key "6", :value "x 44 0 yx 24 7 yx 44 2 yx 49 2 yx 44 7 yx 36 1 yx 17 1 y"} {:process 17, :type :invoke, :f :get, :key "5", :value nil} {:process 46, :type :ok, :f :append, :key "1", :value "x 46 0 y"} {:process 46, :type :invoke, :f :get, :key "5", :value nil} {:process 17, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 y"} {:process 17, :type :invoke, :f :append, :key "4", :value "x 17 4 y"} {:process 8, :type :ok, :f :get, :key "8", :value "x 10 1 y"} {:process 8, :type :invoke, :f :append, :key "2", :value "x 8 1 y"} {:process 46, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 y"} {:process 46, :type :invoke, :f :get, :key "5", :value nil} {:process 2, :type :ok, :f :append, :key "6", :value "x 2 0 y"} {:process 2, :type :invoke, :f :get, :key "4", :value nil} {:process 47, :type :ok, :f :get, :key "1", :value "x 35 16 yx 46 8 yx 23 6 yx 24 0 yx 48 0 yx 34 0 yx 28 0 yx 49 0 yx 49 3 yx 44 6 yx 36 3 yx 41 3 yx 36 5 yx 14 0 yx 46 0 y"} {:process 47, :type :invoke, :f :get, :key "0", :value nil} {:process 17, :type :ok, :f :append, :key "4", :value "x 17 4 y"} {:process 17, :type :invoke, :f :get, :key "4", :value nil} {:process 8, :type :ok, :f :append, :key "2", :value "x 8 1 y"} {:process 8, :type :invoke, :f :append, :key "1", :value "x 8 2 y"} {:process 47, :type :ok, :f :get, :key "0", :value "x 39 0 yx 24 2 yx 15 1 yx 24 4 yx 12 0 yx 21 1 yx 15 7 yx 41 1 yx 36 4 y"} {:process 47, :type :invoke, :f :append, :key "2", :value "x 47 0 y"} {:process 46, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 y"} {:process 46, :type :invoke, :f :append, :key "8", :value "x 46 1 y"} {:process 2, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 y"} {:process 2, :type :invoke, :f :append, :key "0", :value "x 2 1 y"} {:process 17, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 y"} {:process 17, :type :invoke, :f :append, :key "6", :value "x 17 5 y"} {:process 46, :type :ok, :f :append, :key "8", :value "x 46 1 y"} {:process 46, :type :invoke, :f :get, :key "9", :value nil} {:process 8, :type :ok, :f :append, :key "1", :value "x 8 2 y"} {:process 8, :type :invoke, :f :append, :key "0", :value "x 8 3 y"} {:process 47, :type :ok, :f :append, :key "2", :value "x 47 0 y"} {:process 47, :type :invoke, :f :append, :key "5", :value "x 47 1 y"} {:process 2, :type :ok, :f :append, :key "0", :value "x 2 1 y"} {:process 2, :type :invoke, :f :get, :key "0", :value nil} {:process 0, :type :ok, :f :get, :key "7", :value "x 8 0 y"} {:process 0, :type :invoke, :f :get, :key "4", :value nil} {:process 45, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 y"} {:process 45, :type :invoke, :f :append, :key "0", :value "x 45 0 y"} {:process 8, :type :ok, :f :append, :key "0", :value "x 8 3 y"} {:process 8, :type :invoke, :f :append, :key "3", :value "x 8 4 y"} {:process 17, :type :ok, :f :append, :key "6", :value "x 17 5 y"} {:process 17, :type :invoke, :f :get, :key "7", :value nil} {:process 17, :type :ok, :f :get, :key "7", :value "x 8 0 y"} {:process 17, :type :invoke, :f :get, :key "1", :value nil} {:process 0, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 y"} {:process 0, :type :invoke, :f :append, :key "9", :value "x 0 0 y"} {:process 8, :type :ok, :f :append, :key "3", :value "x 8 4 y"} {:process 47, :type :ok, :f :append, :key "5", :value "x 47 1 y"} {:process 8, :type :invoke, :f :get, :key "9", :value nil} {:process 47, :type :invoke, :f :get, :key "5", :value nil} {:process 2, :type :ok, :f :get, :key "0", :value "x 39 0 yx 24 2 yx 15 1 yx 24 4 yx 12 0 yx 21 1 yx 15 7 yx 41 1 yx 36 4 yx 2 1 yx 8 3 y"} {:process 2, :type :invoke, :f :append, :key "4", :value "x 2 2 y"} {:process 47, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 y"} {:process 8, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 y"} {:process 47, :type :invoke, :f :append, :key "4", :value "x 47 2 y"} {:process 8, :type :invoke, :f :append, :key "3", :value "x 8 5 y"} {:process 45, :type :ok, :f :append, :key "0", :value "x 45 0 y"} {:process 45, :type :invoke, :f :put, :key "0", :value "x 45 1 y"} {:process 2, :type :ok, :f :append, :key "4", :value "x 2 2 y"} {:process 2, :type :invoke, :f :get, :key "4", :value nil} {:process 26, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 y"} {:process 26, :type :invoke, :f :get, :key "0", :value nil} {:process 8, :type :ok, :f :append, :key "3", :value "x 8 5 y"} {:process 8, :type :invoke, :f :append, :key "8", :value "x 8 6 y"} {:process 45, :type :ok, :f :put, :key "0", :value "x 45 1 y"} {:process 45, :type :invoke, :f :append, :key "5", :value "x 45 2 y"} {:process 2, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 yx 2 2 y"} {:process 2, :type :invoke, :f :append, :key "8", :value "x 2 3 y"} {:process 47, :type :ok, :f :append, :key "4", :value "x 47 2 y"} {:process 47, :type :invoke, :f :append, :key "0", :value "x 47 3 y"} {:process 45, :type :ok, :f :append, :key "5", :value "x 45 2 y"} {:process 45, :type :invoke, :f :get, :key "5", :value nil} {:process 2, :type :ok, :f :append, :key "8", :value "x 2 3 y"} {:process 2, :type :invoke, :f :get, :key "6", :value nil} {:process 45, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 yx 45 2 y"} {:process 45, :type :invoke, :f :get, :key "6", :value nil} {:process 8, :type :ok, :f :append, :key "8", :value "x 8 6 y"} {:process 8, :type :invoke, :f :append, :key "3", :value "x 8 7 y"} {:process 26, :type :ok, :f :get, :key "0", :value "x 45 1 y"} {:process 26, :type :invoke, :f :put, :key "3", :value "x 26 0 y"} {:process 47, :type :ok, :f :append, :key "0", :value "x 47 3 y"} {:process 47, :type :invoke, :f :get, :key "9", :value nil} {:process 2, :type :ok, :f :get, :key "6", :value "x 44 0 yx 24 7 yx 44 2 yx 49 2 yx 44 7 yx 36 1 yx 17 1 yx 2 0 yx 17 5 y"} {:process 2, :type :invoke, :f :append, :key "1", :value "x 2 4 y"} {:process 8, :type :ok, :f :append, :key "3", :value "x 8 7 y"} {:process 8, :type :invoke, :f :get, :key "4", :value nil} {:process 45, :type :ok, :f :get, :key "6", :value "x 44 0 yx 24 7 yx 44 2 yx 49 2 yx 44 7 yx 36 1 yx 17 1 yx 2 0 yx 17 5 y"} {:process 45, :type :invoke, :f :get, :key "2", :value nil} {:process 45, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 y"} {:process 45, :type :invoke, :f :append, :key "7", :value "x 45 3 y"} {:process 26, :type :ok, :f :put, :key "3", :value "x 26 0 y"} {:process 26, :type :invoke, :f :append, :key "3", :value "x 26 1 y"} {:process 47, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 y"} {:process 47, :type :invoke, :f :append, :key "3", :value "x 47 4 y"} {:process 2, :type :ok, :f :append, :key "1", :value "x 2 4 y"} {:process 2, :type :invoke, :f :append, :key "0", :value "x 2 5 y"} {:process 26, :type :ok, :f :append, :key "3", :value "x 26 1 y"} {:process 26, :type :invoke, :f :append, :key "5", :value "x 26 2 y"} {:process 45, :type :ok, :f :append, :key "7", :value "x 45 3 y"} {:process 45, :type :invoke, :f :get, :key "9", :value nil} {:process 47, :type :ok, :f :append, :key "3", :value "x 47 4 y"} {:process 47, :type :invoke, :f :append, :key "1", :value "x 47 5 y"} {:process 29, :type :ok, :f :get, :key "0", :value "x 45 1 yx 47 3 y"} {:process 29, :type :invoke, :f :append, :key "0", :value "x 29 0 y"} {:process 45, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 y"} {:process 45, :type :invoke, :f :get, :key "9", :value nil} {:process 47, :type :ok, :f :append, :key "1", :value "x 47 5 y"} {:process 47, :type :invoke, :f :get, :key "1", :value nil} {:process 45, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 y"} {:process 45, :type :invoke, :f :append, :key "5", :value "x 45 4 y"} {:process 47, :type :ok, :f :get, :key "1", :value "x 35 16 yx 46 8 yx 23 6 yx 24 0 yx 48 0 yx 34 0 yx 28 0 yx 49 0 yx 49 3 yx 44 6 yx 36 3 yx 41 3 yx 36 5 yx 14 0 yx 46 0 yx 8 2 yx 2 4 yx 47 5 y"} {:process 47, :type :invoke, :f :append, :key "4", :value "x 47 6 y"} {:process 6, :type :ok, :f :append, :key "3", :value "x 6 0 y"} {:process 6, :type :invoke, :f :get, :key "4", :value nil} {:process 39, :type :ok, :f :get, :key "7", :value "x 8 0 yx 45 3 y"} {:process 39, :type :invoke, :f :get, :key "9", :value nil} {:process 45, :type :ok, :f :append, :key "5", :value "x 45 4 y"} {:process 45, :type :invoke, :f :get, :key "2", :value nil} {:process 47, :type :ok, :f :append, :key "4", :value "x 47 6 y"} {:process 47, :type :invoke, :f :put, :key "1", :value "x 47 7 y"} {:process 6, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 yx 2 2 yx 47 2 yx 47 6 y"} {:process 6, :type :invoke, :f :get, :key "0", :value nil} {:process 45, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 y"} {:process 45, :type :invoke, :f :append, :key "4", :value "x 45 5 y"} {:process 39, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 y"} {:process 39, :type :invoke, :f :get, :key "3", :value nil} {:process 47, :type :ok, :f :put, :key "1", :value "x 47 7 y"} {:process 47, :type :invoke, :f :get, :key "3", :value nil} {:process 39, :type :ok, :f :get, :key "3", :value "x 26 0 yx 26 1 yx 47 4 yx 6 0 y"} {:process 39, :type :invoke, :f :append, :key "5", :value "x 39 2 y"} {:process 23, :type :ok, :f :get, :key "8", :value "x 10 1 yx 46 1 yx 2 3 yx 8 6 y"} {:process 23, :type :invoke, :f :append, :key "1", :value "x 23 0 y"} {:process 25, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 yx 2 2 yx 47 2 yx 47 6 y"} {:process 25, :type :invoke, :f :get, :key "4", :value nil} {:process 45, :type :ok, :f :append, :key "4", :value "x 45 5 y"} {:process 45, :type :invoke, :f :append, :key "6", :value "x 45 6 y"} {:process 6, :type :ok, :f :get, :key "0", :value "x 45 1 yx 47 3 yx 29 0 y"} {:process 6, :type :invoke, :f :get, :key "3", :value nil} {:process 35, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 y"} {:process 35, :type :invoke, :f :append, :key "7", :value "x 35 0 y"} {:process 47, :type :ok, :f :get, :key "3", :value "x 26 0 yx 26 1 yx 47 4 yx 6 0 y"} {:process 47, :type :invoke, :f :append, :key "1", :value "x 47 8 y"} {:process 48, :type :ok, :f :append, :key "6", :value "x 48 1 y"} {:process 48, :type :invoke, :f :append, :key "9", :value "x 48 2 y"} {:process 45, :type :ok, :f :append, :key "6", :value "x 45 6 y"} {:process 45, :type :invoke, :f :append, :key "7", :value "x 45 7 y"} {:process 23, :type :ok, :f :append, :key "1", :value "x 23 0 y"} {:process 23, :type :invoke, :f :get, :key "6", :value nil} {:process 35, :type :ok, :f :append, :key "7", :value "x 35 0 y"} {:process 35, :type :invoke, :f :append, :key "3", :value "x 35 1 y"} {:process 25, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 yx 2 2 yx 47 2 yx 47 6 yx 45 5 y"} {:process 25, :type :invoke, :f :append, :key "2", :value "x 25 0 y"} {:process 6, :type :ok, :f :get, :key "3", :value "x 26 0 yx 26 1 yx 47 4 yx 6 0 y"} {:process 6, :type :invoke, :f :append, :key "5", :value "x 6 1 y"} {:process 25, :type :ok, :f :append, :key "2", :value "x 25 0 y"} {:process 45, :type :ok, :f :append, :key "7", :value "x 45 7 y"} {:process 25, :type :invoke, :f :append, :key "4", :value "x 25 1 y"} {:process 45, :type :invoke, :f :append, :key "9", :value "x 45 8 y"} {:process 6, :type :ok, :f :append, :key "5", :value "x 6 1 y"} {:process 6, :type :invoke, :f :get, :key "2", :value nil} {:process 23, :type :ok, :f :get, :key "6", :value "x 44 0 yx 24 7 yx 44 2 yx 49 2 yx 44 7 yx 36 1 yx 17 1 yx 2 0 yx 17 5 yx 48 1 yx 45 6 y"} {:process 23, :type :invoke, :f :append, :key "9", :value "x 23 1 y"} {:process 25, :type :ok, :f :append, :key "4", :value "x 25 1 y"} {:process 25, :type :invoke, :f :append, :key "1", :value "x 25 2 y"} {:process 45, :type :ok, :f :append, :key "9", :value "x 45 8 y"} {:process 45, :type :invoke, :f :get, :key "2", :value nil} {:process 23, :type :ok, :f :append, :key "9", :value "x 23 1 y"} {:process 23, :type :invoke, :f :append, :key "6", :value "x 23 2 y"} {:process 6, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 y"} {:process 6, :type :invoke, :f :append, :key "3", :value "x 6 2 y"} {:process 25, :type :ok, :f :append, :key "1", :value "x 25 2 y"} {:process 30, :type :ok, :f :append, :key "9", :value "x 30 2 y"} {:process 30, :type :invoke, :f :get, :key "6", :value nil} {:process 25, :type :invoke, :f :append, :key "2", :value "x 25 3 y"} {:process 7, :type :ok, :f :append, :key "8", :value "x 7 0 y"} {:process 7, :type :invoke, :f :append, :key "5", :value "x 7 1 y"} {:process 23, :type :ok, :f :append, :key "6", :value "x 23 2 y"} {:process 23, :type :invoke, :f :get, :key "2", :value nil} {:process 45, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 y"} {:process 45, :type :invoke, :f :get, :key "3", :value nil} {:process 23, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 y"} {:process 23, :type :invoke, :f :get, :key "7", :value nil} {:process 6, :type :ok, :f :append, :key "3", :value "x 6 2 y"} {:process 6, :type :invoke, :f :append, :key "1", :value "x 6 3 y"} {:process 7, :type :ok, :f :append, :key "5", :value "x 7 1 y"} {:process 7, :type :invoke, :f :get, :key "5", :value nil} {:process 21, :type :ok, :f :append, :key "9", :value "x 21 3 y"} {:process 21, :type :invoke, :f :put, :key "3", :value "x 21 4 y"} {:process 30, :type :ok, :f :get, :key "6", :value "x 44 0 yx 24 7 yx 44 2 yx 49 2 yx 44 7 yx 36 1 yx 17 1 yx 2 0 yx 17 5 yx 48 1 yx 45 6 yx 23 2 y"} {:process 30, :type :invoke, :f :get, :key "5", :value nil} {:process 6, :type :ok, :f :append, :key "1", :value "x 6 3 y"} {:process 6, :type :invoke, :f :get, :key "9", :value nil} {:process 28, :type :ok, :f :get, :key "6", :value "x 44 0 yx 24 7 yx 44 2 yx 49 2 yx 44 7 yx 36 1 yx 17 1 yx 2 0 yx 17 5 yx 48 1 yx 45 6 yx 23 2 y"} {:process 28, :type :invoke, :f :append, :key "6", :value "x 28 2 y"} {:process 45, :type :ok, :f :get, :key "3", :value "x 26 0 yx 26 1 yx 47 4 yx 6 0 yx 35 1 yx 6 2 y"} {:process 45, :type :invoke, :f :append, :key "9", :value "x 45 9 y"} {:process 21, :type :ok, :f :put, :key "3", :value "x 21 4 y"} {:process 21, :type :invoke, :f :append, :key "8", :value "x 21 5 y"} {:process 12, :type :ok, :f :get, :key "0", :value "x 45 1 yx 47 3 yx 29 0 y"} {:process 12, :type :invoke, :f :append, :key "8", :value "x 12 1 y"} {:process 45, :type :ok, :f :append, :key "9", :value "x 45 9 y"} {:process 45, :type :invoke, :f :append, :key "9", :value "x 45 10 y"} {:process 24, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 y"} {:process 30, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 yx 45 2 yx 26 2 yx 45 4 yx 6 1 yx 7 1 y"} {:process 24, :type :invoke, :f :append, :key "2", :value "x 24 8 y"} {:process 30, :type :invoke, :f :append, :key "2", :value "x 30 3 y"} {:process 28, :type :ok, :f :append, :key "6", :value "x 28 2 y"} {:process 28, :type :invoke, :f :append, :key "5", :value "x 28 3 y"} {:process 6, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 y"} {:process 6, :type :invoke, :f :get, :key "4", :value nil} {:process 40, :type :ok, :f :append, :key "1", :value "x 40 0 y"} {:process 40, :type :invoke, :f :get, :key "2", :value nil} {:process 21, :type :ok, :f :append, :key "8", :value "x 21 5 y"} {:process 21, :type :invoke, :f :get, :key "2", :value nil} {:process 28, :type :ok, :f :append, :key "5", :value "x 28 3 y"} {:process 12, :type :ok, :f :append, :key "8", :value "x 12 1 y"} {:process 28, :type :invoke, :f :append, :key "5", :value "x 28 4 y"} {:process 12, :type :invoke, :f :get, :key "6", :value nil} {:process 45, :type :ok, :f :append, :key "9", :value "x 45 10 y"} {:process 45, :type :invoke, :f :get, :key "4", :value nil} {:process 3, :type :ok, :f :append, :key "3", :value "x 3 2 y"} {:process 3, :type :invoke, :f :append, :key "5", :value "x 3 3 y"} {:process 30, :type :ok, :f :append, :key "2", :value "x 30 3 y"} {:process 30, :type :invoke, :f :append, :key "5", :value "x 30 4 y"} {:process 24, :type :ok, :f :append, :key "2", :value "x 24 8 y"} {:process 24, :type :invoke, :f :append, :key "3", :value "x 24 9 y"} {:process 6, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 yx 2 2 yx 47 2 yx 47 6 yx 45 5 yx 25 1 y"} {:process 6, :type :invoke, :f :get, :key "1", :value nil} {:process 5, :type :ok, :f :get, :key "7", :value "x 8 0 yx 45 3 yx 35 0 yx 45 7 y"} {:process 5, :type :invoke, :f :get, :key "1", :value nil} {:process 45, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 yx 2 2 yx 47 2 yx 47 6 yx 45 5 yx 25 1 y"} {:process 45, :type :invoke, :f :append, :key "4", :value "x 45 11 y"} {:process 40, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 y"} {:process 40, :type :invoke, :f :get, :key "4", :value nil} {:process 43, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 y"} {:process 43, :type :invoke, :f :get, :key "6", :value nil} {:process 28, :type :ok, :f :append, :key "5", :value "x 28 4 y"} {:process 28, :type :invoke, :f :get, :key "4", :value nil} {:process 5, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 y"} {:process 5, :type :invoke, :f :get, :key "7", :value nil} {:process 21, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 y"} {:process 21, :type :invoke, :f :append, :key "9", :value "x 21 6 y"} {:process 3, :type :ok, :f :append, :key "5", :value "x 3 3 y"} {:process 3, :type :invoke, :f :get, :key "5", :value nil} {:process 6, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 y"} {:process 6, :type :invoke, :f :get, :key "0", :value nil} {:process 22, :type :ok, :f :append, :key "2", :value "x 22 2 y"} {:process 22, :type :invoke, :f :get, :key "4", :value nil} {:process 30, :type :ok, :f :append, :key "5", :value "x 30 4 y"} {:process 30, :type :invoke, :f :append, :key "7", :value "x 30 5 y"} {:process 24, :type :ok, :f :append, :key "3", :value "x 24 9 y"} {:process 24, :type :invoke, :f :get, :key "9", :value nil} {:process 21, :type :ok, :f :append, :key "9", :value "x 21 6 y"} {:process 21, :type :invoke, :f :append, :key "8", :value "x 21 7 y"} {:process 5, :type :ok, :f :get, :key "7", :value "x 8 0 yx 45 3 yx 35 0 yx 45 7 y"} {:process 5, :type :invoke, :f :get, :key "1", :value nil} {:process 28, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 yx 2 2 yx 47 2 yx 47 6 yx 45 5 yx 25 1 yx 45 11 y"} {:process 28, :type :invoke, :f :get, :key "2", :value nil} {:process 22, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 yx 2 2 yx 47 2 yx 47 6 yx 45 5 yx 25 1 yx 45 11 y"} {:process 22, :type :invoke, :f :append, :key "0", :value "x 22 3 y"} {:process 45, :type :ok, :f :append, :key "4", :value "x 45 11 y"} {:process 45, :type :invoke, :f :get, :key "1", :value nil} {:process 43, :type :ok, :f :get, :key "6", :value "x 44 0 yx 24 7 yx 44 2 yx 49 2 yx 44 7 yx 36 1 yx 17 1 yx 2 0 yx 17 5 yx 48 1 yx 45 6 yx 23 2 yx 28 2 y"} {:process 43, :type :invoke, :f :get, :key "6", :value nil} {:process 3, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 yx 45 2 yx 26 2 yx 45 4 yx 6 1 yx 7 1 yx 28 3 yx 28 4 yx 3 3 yx 30 4 y"} {:process 5, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 y"} {:process 3, :type :invoke, :f :append, :key "0", :value "x 3 4 y"} {:process 5, :type :invoke, :f :append, :key "5", :value "x 5 0 y"} {:process 40, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 yx 2 2 yx 47 2 yx 47 6 yx 45 5 yx 25 1 yx 45 11 y"} {:process 43, :type :ok, :f :get, :key "6", :value "x 44 0 yx 24 7 yx 44 2 yx 49 2 yx 44 7 yx 36 1 yx 17 1 yx 2 0 yx 17 5 yx 48 1 yx 45 6 yx 23 2 yx 28 2 y"} {:process 40, :type :invoke, :f :append, :key "8", :value "x 40 1 y"} {:process 43, :type :invoke, :f :get, :key "2", :value nil} {:process 21, :type :ok, :f :append, :key "8", :value "x 21 7 y"} {:process 21, :type :invoke, :f :get, :key "7", :value nil} {:process 6, :type :ok, :f :get, :key "0", :value "x 45 1 yx 47 3 yx 29 0 y"} {:process 6, :type :invoke, :f :append, :key "6", :value "x 6 4 y"} {:process 3, :type :ok, :f :append, :key "0", :value "x 3 4 y"} {:process 3, :type :invoke, :f :get, :key "1", :value nil} {:process 45, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 y"} {:process 45, :type :invoke, :f :append, :key "5", :value "x 45 12 y"} {:process 28, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 y"} {:process 28, :type :invoke, :f :get, :key "1", :value nil} {:process 5, :type :ok, :f :append, :key "5", :value "x 5 0 y"} {:process 5, :type :invoke, :f :get, :key "1", :value nil} {:process 22, :type :ok, :f :append, :key "0", :value "x 22 3 y"} {:process 22, :type :invoke, :f :append, :key "2", :value "x 22 4 y"} {:process 28, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 y"} {:process 28, :type :invoke, :f :append, :key "0", :value "x 28 5 y"} {:process 45, :type :ok, :f :append, :key "5", :value "x 45 12 y"} {:process 45, :type :invoke, :f :get, :key "0", :value nil} {:process 21, :type :ok, :f :get, :key "7", :value "x 8 0 yx 45 3 yx 35 0 yx 45 7 y"} {:process 21, :type :invoke, :f :get, :key "5", :value nil} {:process 43, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 y"} {:process 43, :type :invoke, :f :append, :key "8", :value "x 43 0 y"} {:process 3, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 y"} {:process 3, :type :invoke, :f :get, :key "5", :value nil} {:process 15, :type :ok, :f :get, :key "8", :value "x 10 1 yx 46 1 yx 2 3 yx 8 6 yx 21 5 yx 12 1 yx 21 7 yx 40 1 y"} {:process 15, :type :invoke, :f :append, :key "2", :value "x 15 9 y"} {:process 31, :type :ok, :f :append, :key "3", :value "x 31 0 y"} {:process 22, :type :ok, :f :append, :key "2", :value "x 22 4 y"} {:process 31, :type :invoke, :f :get, :key "0", :value nil} {:process 22, :type :invoke, :f :append, :key "7", :value "x 22 5 y"} {:process 21, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 yx 45 2 yx 26 2 yx 45 4 yx 6 1 yx 7 1 yx 28 3 yx 28 4 yx 3 3 yx 30 4 yx 5 0 yx 45 12 y"} {:process 21, :type :invoke, :f :append, :key "4", :value "x 21 8 y"} {:process 5, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 y"} {:process 5, :type :invoke, :f :append, :key "9", :value "x 5 1 y"} {:process 3, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 yx 45 2 yx 26 2 yx 45 4 yx 6 1 yx 7 1 yx 28 3 yx 28 4 yx 3 3 yx 30 4 yx 5 0 yx 45 12 y"} {:process 3, :type :invoke, :f :get, :key "4", :value nil} {:process 43, :type :ok, :f :append, :key "8", :value "x 43 0 y"} {:process 43, :type :invoke, :f :get, :key "5", :value nil} {:process 45, :type :ok, :f :get, :key "0", :value "x 45 1 yx 47 3 yx 29 0 yx 3 4 yx 22 3 y"} {:process 45, :type :invoke, :f :append, :key "2", :value "x 45 13 y"} {:process 28, :type :ok, :f :append, :key "0", :value "x 28 5 y"} {:process 22, :type :ok, :f :append, :key "7", :value "x 22 5 y"} {:process 28, :type :invoke, :f :append, :key "3", :value "x 28 6 y"} {:process 22, :type :invoke, :f :get, :key "7", :value nil} {:process 31, :type :ok, :f :get, :key "0", :value "x 45 1 yx 47 3 yx 29 0 yx 3 4 yx 22 3 yx 28 5 y"} {:process 31, :type :invoke, :f :get, :key "0", :value nil} {:process 3, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 yx 2 2 yx 47 2 yx 47 6 yx 45 5 yx 25 1 yx 45 11 y"} {:process 3, :type :invoke, :f :get, :key "7", :value nil} {:process 45, :type :ok, :f :append, :key "2", :value "x 45 13 y"} {:process 45, :type :invoke, :f :get, :key "6", :value nil} {:process 43, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 yx 45 2 yx 26 2 yx 45 4 yx 6 1 yx 7 1 yx 28 3 yx 28 4 yx 3 3 yx 30 4 yx 5 0 yx 45 12 y"} {:process 43, :type :invoke, :f :get, :key "2", :value nil} {:process 5, :type :ok, :f :append, :key "9", :value "x 5 1 y"} {:process 5, :type :invoke, :f :append, :key "3", :value "x 5 2 y"} {:process 28, :type :ok, :f :append, :key "3", :value "x 28 6 y"} {:process 28, :type :invoke, :f :append, :key "1", :value "x 28 7 y"} {:process 31, :type :ok, :f :get, :key "0", :value "x 45 1 yx 47 3 yx 29 0 yx 3 4 yx 22 3 yx 28 5 y"} {:process 43, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 y"} {:process 31, :type :invoke, :f :get, :key "1", :value nil} {:process 43, :type :invoke, :f :get, :key "4", :value nil} {:process 5, :type :ok, :f :append, :key "3", :value "x 5 2 y"} {:process 5, :type :invoke, :f :append, :key "7", :value "x 5 3 y"} {:process 22, :type :ok, :f :get, :key "7", :value "x 8 0 yx 45 3 yx 35 0 yx 45 7 yx 22 5 y"} {:process 22, :type :invoke, :f :put, :key "6", :value "x 22 6 y"} {:process 20, :type :ok, :f :append, :key "3", :value "x 20 1 y"} {:process 20, :type :invoke, :f :append, :key "7", :value "x 20 2 y"} {:process 45, :type :ok, :f :get, :key "6", :value "x 44 0 yx 24 7 yx 44 2 yx 49 2 yx 44 7 yx 36 1 yx 17 1 yx 2 0 yx 17 5 yx 48 1 yx 45 6 yx 23 2 yx 28 2 y"} {:process 45, :type :invoke, :f :append, :key "9", :value "x 45 14 y"} {:process 43, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 yx 2 2 yx 47 2 yx 47 6 yx 45 5 yx 25 1 yx 45 11 y"} {:process 43, :type :invoke, :f :get, :key "4", :value nil} {:process 31, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 y"} {:process 31, :type :invoke, :f :get, :key "2", :value nil} {:process 33, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 y"} {:process 33, :type :invoke, :f :append, :key "5", :value "x 33 0 y"} {:process 22, :type :ok, :f :put, :key "6", :value "x 22 6 y"} {:process 22, :type :invoke, :f :append, :key "9", :value "x 22 7 y"} {:process 45, :type :ok, :f :append, :key "9", :value "x 45 14 y"} {:process 45, :type :invoke, :f :get, :key "6", :value nil} {:process 31, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 y"} {:process 31, :type :invoke, :f :get, :key "7", :value nil} {:process 20, :type :ok, :f :append, :key "7", :value "x 20 2 y"} {:process 20, :type :invoke, :f :get, :key "1", :value nil} {:process 44, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 y"} {:process 44, :type :invoke, :f :put, :key "3", :value "x 44 11 y"} {:process 33, :type :ok, :f :append, :key "5", :value "x 33 0 y"} {:process 33, :type :invoke, :f :get, :key "3", :value nil} {:process 22, :type :ok, :f :append, :key "9", :value "x 22 7 y"} {:process 22, :type :invoke, :f :get, :key "6", :value nil} {:process 20, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 y"} {:process 20, :type :invoke, :f :get, :key "2", :value nil} {:process 31, :type :ok, :f :get, :key "7", :value "x 8 0 yx 45 3 yx 35 0 yx 45 7 yx 22 5 yx 20 2 y"} {:process 31, :type :invoke, :f :get, :key "2", :value nil} {:process 33, :type :ok, :f :get, :key "3", :value "x 21 4 yx 24 9 yx 31 0 yx 28 6 yx 5 2 y"} {:process 33, :type :invoke, :f :get, :key "5", :value nil} {:process 22, :type :ok, :f :get, :key "6", :value "x 22 6 y"} {:process 22, :type :invoke, :f :get, :key "7", :value nil} {:process 31, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 y"} {:process 31, :type :invoke, :f :get, :key "4", :value nil} {:process 20, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 y"} {:process 20, :type :invoke, :f :append, :key "1", :value "x 20 3 y"} {:process 19, :type :ok, :f :append, :key "4", :value "x 19 1 y"} {:process 19, :type :invoke, :f :get, :key "8", :value nil} {:process 38, :type :ok, :f :get, :key "0", :value "x 45 1 yx 47 3 yx 29 0 yx 3 4 yx 22 3 yx 28 5 y"} {:process 33, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 yx 45 2 yx 26 2 yx 45 4 yx 6 1 yx 7 1 yx 28 3 yx 28 4 yx 3 3 yx 30 4 yx 5 0 yx 45 12 yx 33 0 y"} {:process 38, :type :invoke, :f :get, :key "9", :value nil} {:process 33, :type :invoke, :f :append, :key "5", :value "x 33 1 y"} {:process 31, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 yx 2 2 yx 47 2 yx 47 6 yx 45 5 yx 25 1 yx 45 11 y"} {:process 31, :type :invoke, :f :append, :key "5", :value "x 31 1 y"} {:process 22, :type :ok, :f :get, :key "7", :value "x 8 0 yx 45 3 yx 35 0 yx 45 7 yx 22 5 yx 20 2 y"} {:process 22, :type :invoke, :f :append, :key "2", :value "x 22 8 y"} {:process 18, :type :ok, :f :append, :key "7", :value "x 18 0 y"} {:process 20, :type :ok, :f :append, :key "1", :value "x 20 3 y"} {:process 18, :type :invoke, :f :append, :key "9", :value "x 18 1 y"} {:process 20, :type :invoke, :f :append, :key "6", :value "x 20 4 y"} {:process 33, :type :ok, :f :append, :key "5", :value "x 33 1 y"} {:process 33, :type :invoke, :f :append, :key "1", :value "x 33 2 y"} {:process 38, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 y"} {:process 38, :type :invoke, :f :append, :key "0", :value "x 38 0 y"} {:process 42, :type :ok, :f :append, :key "1", :value "x 42 2 y"} {:process 42, :type :invoke, :f :get, :key "5", :value nil} {:process 20, :type :ok, :f :append, :key "6", :value "x 20 4 y"} {:process 20, :type :invoke, :f :get, :key "1", :value nil} {:process 31, :type :ok, :f :append, :key "5", :value "x 31 1 y"} {:process 31, :type :invoke, :f :append, :key "0", :value "x 31 2 y"} {:process 18, :type :ok, :f :append, :key "9", :value "x 18 1 y"} {:process 18, :type :invoke, :f :get, :key "6", :value nil} {:process 4, :type :ok, :f :append, :key "6", :value "x 4 2 y"} {:process 4, :type :invoke, :f :append, :key "4", :value "x 4 3 y"} {:process 16, :type :ok, :f :append, :key "2", :value "x 16 0 y"} {:process 16, :type :invoke, :f :get, :key "3", :value nil} {:process 42, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 yx 45 2 yx 26 2 yx 45 4 yx 6 1 yx 7 1 yx 28 3 yx 28 4 yx 3 3 yx 30 4 yx 5 0 yx 45 12 yx 33 0 yx 33 1 yx 31 1 y"} {:process 42, :type :invoke, :f :append, :key "9", :value "x 42 3 y"} {:process 16, :type :ok, :f :get, :key "3", :value "x 21 4 yx 24 9 yx 31 0 yx 28 6 yx 5 2 y"} {:process 16, :type :invoke, :f :append, :key "9", :value "x 16 1 y"} {:process 31, :type :ok, :f :append, :key "0", :value "x 31 2 y"} {:process 31, :type :invoke, :f :append, :key "2", :value "x 31 3 y"} {:process 20, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 y"} {:process 20, :type :invoke, :f :get, :key "2", :value nil} {:process 18, :type :ok, :f :get, :key "6", :value "x 22 6 yx 20 4 yx 4 2 y"} {:process 4, :type :ok, :f :append, :key "4", :value "x 4 3 y"} {:process 18, :type :invoke, :f :append, :key "1", :value "x 18 2 y"} {:process 4, :type :invoke, :f :get, :key "0", :value nil} {:process 38, :type :ok, :f :append, :key "0", :value "x 38 0 y"} {:process 38, :type :invoke, :f :get, :key "8", :value nil} {:process 42, :type :ok, :f :append, :key "9", :value "x 42 3 y"} {:process 42, :type :invoke, :f :append, :key "5", :value "x 42 4 y"} {:process 41, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 y"} {:process 41, :type :invoke, :f :put, :key "8", :value "x 41 6 y"} {:process 4, :type :ok, :f :get, :key "0", :value "x 45 1 yx 47 3 yx 29 0 yx 3 4 yx 22 3 yx 28 5 yx 31 2 yx 38 0 y"} {:process 4, :type :invoke, :f :append, :key "1", :value "x 4 4 y"} {:process 16, :type :ok, :f :append, :key "9", :value "x 16 1 y"} {:process 16, :type :invoke, :f :get, :key "5", :value nil} {:process 36, :type :ok, :f :append, :key "5", :value "x 36 7 y"} {:process 36, :type :invoke, :f :append, :key "4", :value "x 36 8 y"} {:process 18, :type :ok, :f :append, :key "1", :value "x 18 2 y"} {:process 18, :type :invoke, :f :append, :key "5", :value "x 18 3 y"} {:process 41, :type :ok, :f :put, :key "8", :value "x 41 6 y"} {:process 41, :type :invoke, :f :append, :key "7", :value "x 41 7 y"} {:process 36, :type :ok, :f :append, :key "4", :value "x 36 8 y"} {:process 36, :type :invoke, :f :append, :key "7", :value "x 36 9 y"} {:process 4, :type :ok, :f :append, :key "1", :value "x 4 4 y"} {:process 4, :type :invoke, :f :append, :key "4", :value "x 4 5 y"} {:process 16, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 yx 45 2 yx 26 2 yx 45 4 yx 6 1 yx 7 1 yx 28 3 yx 28 4 yx 3 3 yx 30 4 yx 5 0 yx 45 12 yx 33 0 yx 33 1 yx 31 1 yx 42 4 y"} {:process 16, :type :invoke, :f :get, :key "9", :value nil} {:process 14, :type :ok, :f :get, :key "7", :value "x 8 0 yx 45 3 yx 35 0 yx 45 7 yx 22 5 yx 20 2 yx 18 0 y"} {:process 14, :type :invoke, :f :get, :key "5", :value nil} {:process 18, :type :ok, :f :append, :key "5", :value "x 18 3 y"} {:process 18, :type :invoke, :f :append, :key "0", :value "x 18 4 y"} {:process 18, :type :ok, :f :append, :key "0", :value "x 18 4 y"} {:process 36, :type :ok, :f :append, :key "7", :value "x 36 9 y"} {:process 18, :type :invoke, :f :get, :key "7", :value nil} {:process 36, :type :invoke, :f :append, :key "3", :value "x 36 10 y"} {:process 41, :type :ok, :f :append, :key "7", :value "x 41 7 y"} {:process 41, :type :invoke, :f :get, :key "3", :value nil} {:process 16, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 y"} {:process 16, :type :invoke, :f :get, :key "4", :value nil} {:process 4, :type :ok, :f :append, :key "4", :value "x 4 5 y"} {:process 4, :type :invoke, :f :append, :key "9", :value "x 4 6 y"} {:process 11, :type :ok, :f :append, :key "4", :value "x 11 0 y"} {:process 11, :type :invoke, :f :append, :key "4", :value "x 11 1 y"} {:process 14, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 yx 45 2 yx 26 2 yx 45 4 yx 6 1 yx 7 1 yx 28 3 yx 28 4 yx 3 3 yx 30 4 yx 5 0 yx 45 12 yx 33 0 yx 33 1 yx 31 1 yx 42 4 yx 18 3 y"} {:process 14, :type :invoke, :f :append, :key "4", :value "x 14 1 y"} {:process 18, :type :ok, :f :get, :key "7", :value "x 8 0 yx 45 3 yx 35 0 yx 45 7 yx 22 5 yx 20 2 yx 18 0 yx 41 7 yx 36 9 y"} {:process 18, :type :invoke, :f :get, :key "9", :value nil} {:process 36, :type :ok, :f :append, :key "3", :value "x 36 10 y"} {:process 36, :type :invoke, :f :append, :key "1", :value "x 36 11 y"} {:process 11, :type :ok, :f :append, :key "4", :value "x 11 1 y"} {:process 11, :type :invoke, :f :get, :key "5", :value nil} {:process 18, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 y"} {:process 18, :type :invoke, :f :get, :key "5", :value nil} {:process 41, :type :ok, :f :get, :key "3", :value "x 21 4 yx 24 9 yx 31 0 yx 28 6 yx 5 2 yx 36 10 y"} {:process 41, :type :invoke, :f :append, :key "3", :value "x 41 8 y"} {:process 16, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 yx 2 2 yx 47 2 yx 47 6 yx 45 5 yx 25 1 yx 45 11 yx 4 3 yx 36 8 yx 4 5 yx 11 0 yx 11 1 y"} {:process 16, :type :invoke, :f :get, :key "2", :value nil} {:process 14, :type :ok, :f :append, :key "4", :value "x 14 1 y"} {:process 14, :type :invoke, :f :append, :key "7", :value "x 14 2 y"} {:process 4, :type :ok, :f :append, :key "9", :value "x 4 6 y"} {:process 4, :type :invoke, :f :append, :key "3", :value "x 4 7 y"} {:process 0, :type :ok, :f :append, :key "9", :value "x 0 0 y"} {:process 0, :type :invoke, :f :get, :key "8", :value nil} {:process 11, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 yx 45 2 yx 26 2 yx 45 4 yx 6 1 yx 7 1 yx 28 3 yx 28 4 yx 3 3 yx 30 4 yx 5 0 yx 45 12 yx 33 0 yx 33 1 yx 31 1 yx 42 4 yx 18 3 y"} {:process 17, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 y"} {:process 17, :type :invoke, :f :append, :key "4", :value "x 17 6 y"} {:process 11, :type :invoke, :f :append, :key "8", :value "x 11 2 y"} {:process 14, :type :ok, :f :append, :key "7", :value "x 14 2 y"} {:process 14, :type :invoke, :f :append, :key "2", :value "x 14 3 y"} {:process 41, :type :ok, :f :append, :key "3", :value "x 41 8 y"} {:process 41, :type :invoke, :f :append, :key "9", :value "x 41 9 y"} {:process 18, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 yx 45 2 yx 26 2 yx 45 4 yx 6 1 yx 7 1 yx 28 3 yx 28 4 yx 3 3 yx 30 4 yx 5 0 yx 45 12 yx 33 0 yx 33 1 yx 31 1 yx 42 4 yx 18 3 y"} {:process 18, :type :invoke, :f :get, :key "5", :value nil} {:process 4, :type :ok, :f :append, :key "3", :value "x 4 7 y"} {:process 4, :type :invoke, :f :get, :key "1", :value nil} {:process 0, :type :ok, :f :get, :key "8", :value "x 41 6 y"} {:process 0, :type :invoke, :f :get, :key "5", :value nil} {:process 11, :type :ok, :f :append, :key "8", :value "x 11 2 y"} {:process 11, :type :invoke, :f :get, :key "9", :value nil} {:process 17, :type :ok, :f :append, :key "4", :value "x 17 6 y"} {:process 17, :type :invoke, :f :append, :key "1", :value "x 17 7 y"} {:process 11, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 y"} {:process 11, :type :invoke, :f :append, :key "2", :value "x 11 3 y"} {:process 41, :type :ok, :f :append, :key "9", :value "x 41 9 y"} {:process 41, :type :invoke, :f :append, :key "6", :value "x 41 10 y"} {:process 12, :type :ok, :f :get, :key "6", :value "x 22 6 yx 20 4 yx 4 2 yx 41 10 y"} {:process 12, :type :invoke, :f :get, :key "6", :value nil} {:process 24, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 y"} {:process 24, :type :invoke, :f :append, :key "9", :value "x 24 10 y"} {:process 34, :type :ok, :f :get, :key "3", :value "x 21 4 yx 24 9 yx 31 0 yx 28 6 yx 5 2 yx 36 10 yx 41 8 yx 4 7 y"} {:process 34, :type :invoke, :f :get, :key "5", :value nil} {:process 24, :type :ok, :f :append, :key "9", :value "x 24 10 y"} {:process 24, :type :invoke, :f :put, :key "6", :value "x 24 11 y"} {:process 16, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 yx 22 8 yx 14 3 y"} {:process 16, :type :invoke, :f :append, :key "5", :value "x 16 2 y"} {:process 13, :type :ok, :f :append, :key "9", :value "x 13 0 y"} {:process 13, :type :invoke, :f :append, :key "6", :value "x 13 1 y"} {:process 46, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 y"} {:process 46, :type :invoke, :f :append, :key "0", :value "x 46 2 y"} {:process 16, :type :ok, :f :append, :key "5", :value "x 16 2 y"} {:process 16, :type :invoke, :f :get, :key "1", :value nil} {:process 24, :type :ok, :f :put, :key "6", :value "x 24 11 y"} {:process 24, :type :invoke, :f :append, :key "9", :value "x 24 12 y"} {:process 45, :type :ok, :f :get, :key "6", :value "x 24 11 yx 13 1 y"} {:process 45, :type :invoke, :f :get, :key "9", :value nil} {:process 17, :type :ok, :f :append, :key "1", :value "x 17 7 y"} {:process 17, :type :invoke, :f :get, :key "0", :value nil} {:process 46, :type :ok, :f :append, :key "0", :value "x 46 2 y"} {:process 46, :type :invoke, :f :append, :key "0", :value "x 46 3 y"} {:process 28, :type :ok, :f :append, :key "1", :value "x 28 7 y"} {:process 32, :type :ok, :f :get, :key "8", :value "x 41 6 yx 11 2 y"} {:process 28, :type :invoke, :f :append, :key "6", :value "x 28 8 y"} {:process 32, :type :invoke, :f :get, :key "4", :value nil} {:process 24, :type :ok, :f :append, :key "9", :value "x 24 12 y"} {:process 24, :type :invoke, :f :append, :key "5", :value "x 24 13 y"} {:process 45, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 y"} {:process 45, :type :invoke, :f :append, :key "1", :value "x 45 15 y"} {:process 18, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 yx 45 2 yx 26 2 yx 45 4 yx 6 1 yx 7 1 yx 28 3 yx 28 4 yx 3 3 yx 30 4 yx 5 0 yx 45 12 yx 33 0 yx 33 1 yx 31 1 yx 42 4 yx 18 3 yx 16 2 y"} {:process 18, :type :invoke, :f :get, :key "3", :value nil} {:process 24, :type :ok, :f :append, :key "5", :value "x 24 13 y"} {:process 24, :type :invoke, :f :put, :key "7", :value "x 24 14 y"} {:process 17, :type :ok, :f :get, :key "0", :value "x 45 1 yx 47 3 yx 29 0 yx 3 4 yx 22 3 yx 28 5 yx 31 2 yx 38 0 yx 18 4 yx 46 2 y"} {:process 17, :type :invoke, :f :append, :key "2", :value "x 17 8 y"} {:process 45, :type :ok, :f :append, :key "1", :value "x 45 15 y"} {:process 45, :type :invoke, :f :append, :key "7", :value "x 45 16 y"} {:process 49, :type :ok, :f :append, :key "1", :value "x 49 3 y"} {:process 49, :type :invoke, :f :put, :key "6", :value "x 49 4 y"} {:process 17, :type :ok, :f :append, :key "2", :value "x 17 8 y"} {:process 17, :type :invoke, :f :append, :key "9", :value "x 17 9 y"} {:process 18, :type :ok, :f :get, :key "3", :value "x 21 4 yx 24 9 yx 31 0 yx 28 6 yx 5 2 yx 36 10 yx 41 8 yx 4 7 y"} {:process 18, :type :invoke, :f :append, :key "6", :value "x 18 5 y"} {:process 45, :type :ok, :f :append, :key "7", :value "x 45 16 y"} {:process 45, :type :invoke, :f :append, :key "6", :value "x 45 17 y"} {:process 24, :type :ok, :f :put, :key "7", :value "x 24 14 y"} {:process 24, :type :invoke, :f :append, :key "4", :value "x 24 15 y"} {:process 49, :type :ok, :f :put, :key "6", :value "x 49 4 y"} {:process 49, :type :invoke, :f :get, :key "9", :value nil} {:process 3, :type :ok, :f :get, :key "7", :value "x 24 14 y"} {:process 3, :type :invoke, :f :append, :key "9", :value "x 3 5 y"} {:process 17, :type :ok, :f :append, :key "9", :value "x 17 9 y"} {:process 17, :type :invoke, :f :append, :key "1", :value "x 17 10 y"} {:process 49, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 y"} {:process 49, :type :invoke, :f :append, :key "6", :value "x 49 5 y"} {:process 24, :type :ok, :f :append, :key "4", :value "x 24 15 y"} {:process 24, :type :invoke, :f :get, :key "2", :value nil} {:process 45, :type :ok, :f :append, :key "6", :value "x 45 17 y"} {:process 45, :type :invoke, :f :get, :key "6", :value nil} {:process 3, :type :ok, :f :append, :key "9", :value "x 3 5 y"} {:process 3, :type :invoke, :f :get, :key "6", :value nil} {:process 17, :type :ok, :f :append, :key "1", :value "x 17 10 y"} {:process 17, :type :invoke, :f :append, :key "9", :value "x 17 11 y"} {:process 49, :type :ok, :f :append, :key "6", :value "x 49 5 y"} {:process 49, :type :invoke, :f :get, :key "5", :value nil} {:process 0, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 yx 45 2 yx 26 2 yx 45 4 yx 6 1 yx 7 1 yx 28 3 yx 28 4 yx 3 3 yx 30 4 yx 5 0 yx 45 12 yx 33 0 yx 33 1 yx 31 1 yx 42 4 yx 18 3 yx 16 2 yx 24 13 y"} {:process 0, :type :invoke, :f :get, :key "4", :value nil} {:process 24, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 yx 22 8 yx 14 3 yx 17 8 y"} {:process 24, :type :invoke, :f :get, :key "3", :value nil} {:process 3, :type :ok, :f :get, :key "6", :value "x 49 4 yx 45 17 yx 49 5 y"} {:process 3, :type :invoke, :f :append, :key "8", :value "x 3 6 y"} {:process 21, :type :ok, :f :append, :key "4", :value "x 21 8 y"} {:process 21, :type :invoke, :f :get, :key "3", :value nil} {:process 0, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 yx 2 2 yx 47 2 yx 47 6 yx 45 5 yx 25 1 yx 45 11 yx 4 3 yx 36 8 yx 4 5 yx 11 0 yx 11 1 yx 14 1 yx 17 6 yx 24 15 yx 21 8 y"} {:process 0, :type :invoke, :f :put, :key "6", :value "x 0 1 y"} {:process 45, :type :ok, :f :get, :key "6", :value "x 49 4 yx 45 17 yx 49 5 y"} {:process 45, :type :invoke, :f :get, :key "6", :value nil} {:process 3, :type :ok, :f :append, :key "8", :value "x 3 6 y"} {:process 3, :type :invoke, :f :get, :key "1", :value nil} {:process 17, :type :ok, :f :append, :key "9", :value "x 17 11 y"} {:process 17, :type :invoke, :f :append, :key "2", :value "x 17 12 y"} {:process 24, :type :ok, :f :get, :key "3", :value "x 21 4 yx 24 9 yx 31 0 yx 28 6 yx 5 2 yx 36 10 yx 41 8 yx 4 7 y"} {:process 24, :type :invoke, :f :append, :key "8", :value "x 24 16 y"} {:process 49, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 yx 45 2 yx 26 2 yx 45 4 yx 6 1 yx 7 1 yx 28 3 yx 28 4 yx 3 3 yx 30 4 yx 5 0 yx 45 12 yx 33 0 yx 33 1 yx 31 1 yx 42 4 yx 18 3 yx 16 2 yx 24 13 y"} {:process 49, :type :invoke, :f :append, :key "8", :value "x 49 6 y"} {:process 11, :type :ok, :f :append, :key "2", :value "x 11 3 y"} {:process 11, :type :invoke, :f :get, :key "8", :value nil} {:process 21, :type :ok, :f :get, :key "3", :value "x 21 4 yx 24 9 yx 31 0 yx 28 6 yx 5 2 yx 36 10 yx 41 8 yx 4 7 y"} {:process 21, :type :invoke, :f :get, :key "7", :value nil} {:process 38, :type :ok, :f :get, :key "8", :value "x 41 6 yx 11 2 yx 3 6 y"} {:process 38, :type :invoke, :f :append, :key "9", :value "x 38 1 y"} {:process 0, :type :ok, :f :put, :key "6", :value "x 0 1 y"} {:process 0, :type :invoke, :f :get, :key "9", :value nil} {:process 6, :type :ok, :f :append, :key "6", :value "x 6 4 y"} {:process 6, :type :invoke, :f :get, :key "6", :value nil} {:process 45, :type :ok, :f :get, :key "6", :value "x 0 1 yx 6 4 y"} {:process 45, :type :invoke, :f :append, :key "0", :value "x 45 18 y"} {:process 27, :type :ok, :f :append, :key "3", :value "x 27 0 y"} {:process 27, :type :invoke, :f :get, :key "4", :value nil} {:process 21, :type :ok, :f :get, :key "7", :value "x 24 14 y"} {:process 21, :type :invoke, :f :get, :key "4", :value nil} {:process 49, :type :ok, :f :append, :key "8", :value "x 49 6 y"} {:process 49, :type :invoke, :f :get, :key "2", :value nil} {:process 38, :type :ok, :f :append, :key "9", :value "x 38 1 y"} {:process 38, :type :invoke, :f :get, :key "4", :value nil} {:process 0, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 y"} {:process 0, :type :invoke, :f :append, :key "2", :value "x 0 2 y"} {:process 24, :type :ok, :f :append, :key "8", :value "x 24 16 y"} {:process 24, :type :invoke, :f :append, :key "6", :value "x 24 17 y"} {:process 9, :type :ok, :f :append, :key "0", :value "x 9 1 y"} {:process 9, :type :invoke, :f :get, :key "1", :value nil} {:process 49, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 yx 22 8 yx 14 3 yx 17 8 yx 11 3 yx 17 12 y"} {:process 49, :type :invoke, :f :get, :key "8", :value nil} {:process 45, :type :ok, :f :append, :key "0", :value "x 45 18 y"} {:process 45, :type :invoke, :f :append, :key "6", :value "x 45 19 y"} {:process 24, :type :ok, :f :append, :key "6", :value "x 24 17 y"} {:process 24, :type :invoke, :f :append, :key "7", :value "x 24 18 y"} {:process 15, :type :ok, :f :append, :key "2", :value "x 15 9 y"} {:process 21, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 yx 2 2 yx 47 2 yx 47 6 yx 45 5 yx 25 1 yx 45 11 yx 4 3 yx 36 8 yx 4 5 yx 11 0 yx 11 1 yx 14 1 yx 17 6 yx 24 15 yx 21 8 y"} {:process 15, :type :invoke, :f :get, :key "4", :value nil} {:process 21, :type :invoke, :f :get, :key "6", :value nil} {:process 27, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 yx 2 2 yx 47 2 yx 47 6 yx 45 5 yx 25 1 yx 45 11 yx 4 3 yx 36 8 yx 4 5 yx 11 0 yx 11 1 yx 14 1 yx 17 6 yx 24 15 yx 21 8 y"} {:process 27, :type :invoke, :f :get, :key "8", :value nil} {:process 38, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 yx 2 2 yx 47 2 yx 47 6 yx 45 5 yx 25 1 yx 45 11 yx 4 3 yx 36 8 yx 4 5 yx 11 0 yx 11 1 yx 14 1 yx 17 6 yx 24 15 yx 21 8 y"} {:process 0, :type :ok, :f :append, :key "2", :value "x 0 2 y"} {:process 38, :type :invoke, :f :get, :key "2", :value nil} {:process 0, :type :invoke, :f :get, :key "8", :value nil} {:process 10, :type :ok, :f :append, :key "8", :value "x 10 2 y"} {:process 10, :type :invoke, :f :get, :key "0", :value nil} {:process 24, :type :ok, :f :append, :key "7", :value "x 24 18 y"} {:process 24, :type :invoke, :f :get, :key "0", :value nil} {:process 10, :type :ok, :f :get, :key "0", :value "x 45 1 yx 47 3 yx 29 0 yx 3 4 yx 22 3 yx 28 5 yx 31 2 yx 38 0 yx 18 4 yx 46 2 yx 46 3 yx 9 1 yx 45 18 y"} {:process 27, :type :ok, :f :get, :key "8", :value "x 41 6 yx 11 2 yx 3 6 yx 49 6 yx 24 16 y"} {:process 10, :type :invoke, :f :get, :key "1", :value nil} {:process 27, :type :invoke, :f :append, :key "6", :value "x 27 1 y"} {:process 0, :type :ok, :f :get, :key "8", :value "x 41 6 yx 11 2 yx 3 6 yx 49 6 yx 24 16 y"} {:process 0, :type :invoke, :f :get, :key "0", :value nil} {:process 21, :type :ok, :f :get, :key "6", :value "x 0 1 yx 6 4 yx 24 17 yx 45 19 y"} {:process 21, :type :invoke, :f :get, :key "5", :value nil} {:process 1, :type :ok, :f :get, :key "6", :value "x 0 1 yx 6 4 yx 24 17 yx 45 19 y"} {:process 1, :type :invoke, :f :put, :key "4", :value "x 1 2 y"} {:process 15, :type :ok, :f :get, :key "4", :value "x 37 0 yx 42 0 yx 36 2 yx 19 1 yx 17 4 yx 2 2 yx 47 2 yx 47 6 yx 45 5 yx 25 1 yx 45 11 yx 4 3 yx 36 8 yx 4 5 yx 11 0 yx 11 1 yx 14 1 yx 17 6 yx 24 15 yx 21 8 y"} {:process 15, :type :invoke, :f :append, :key "6", :value "x 15 10 y"} {:process 27, :type :ok, :f :append, :key "6", :value "x 27 1 y"} {:process 38, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 yx 22 8 yx 14 3 yx 17 8 yx 11 3 yx 17 12 yx 15 9 yx 0 2 y"} {:process 27, :type :invoke, :f :get, :key "1", :value nil} {:process 38, :type :invoke, :f :get, :key "2", :value nil} {:process 24, :type :ok, :f :get, :key "0", :value "x 45 1 yx 47 3 yx 29 0 yx 3 4 yx 22 3 yx 28 5 yx 31 2 yx 38 0 yx 18 4 yx 46 2 yx 46 3 yx 9 1 yx 45 18 y"} {:process 24, :type :invoke, :f :append, :key "0", :value "x 24 19 y"} {:process 27, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 y"} {:process 27, :type :invoke, :f :get, :key "0", :value nil} {:process 38, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 yx 22 8 yx 14 3 yx 17 8 yx 11 3 yx 17 12 yx 15 9 yx 0 2 y"} {:process 38, :type :invoke, :f :get, :key "3", :value nil} {:process 21, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 yx 45 2 yx 26 2 yx 45 4 yx 6 1 yx 7 1 yx 28 3 yx 28 4 yx 3 3 yx 30 4 yx 5 0 yx 45 12 yx 33 0 yx 33 1 yx 31 1 yx 42 4 yx 18 3 yx 16 2 yx 24 13 y"} {:process 21, :type :invoke, :f :append, :key "8", :value "x 21 9 y"} {:process 15, :type :ok, :f :append, :key "6", :value "x 15 10 y"} {:process 15, :type :invoke, :f :append, :key "8", :value "x 15 11 y"} {:process 1, :type :ok, :f :put, :key "4", :value "x 1 2 y"} {:process 1, :type :invoke, :f :get, :key "3", :value nil} {:process 38, :type :ok, :f :get, :key "3", :value "x 21 4 yx 24 9 yx 31 0 yx 28 6 yx 5 2 yx 36 10 yx 41 8 yx 4 7 y"} {:process 38, :type :invoke, :f :append, :key "8", :value "x 38 2 y"} {:process 27, :type :ok, :f :get, :key "0", :value "x 45 1 yx 47 3 yx 29 0 yx 3 4 yx 22 3 yx 28 5 yx 31 2 yx 38 0 yx 18 4 yx 46 2 yx 46 3 yx 9 1 yx 45 18 y"} {:process 27, :type :invoke, :f :get, :key "9", :value nil} {:process 24, :type :ok, :f :append, :key "0", :value "x 24 19 y"} {:process 42, :type :ok, :f :append, :key "5", :value "x 42 4 y"} {:process 42, :type :invoke, :f :get, :key "5", :value nil} {:process 24, :type :invoke, :f :get, :key "8", :value nil} {:process 21, :type :ok, :f :append, :key "8", :value "x 21 9 y"} {:process 21, :type :invoke, :f :append, :key "1", :value "x 21 10 y"} {:process 5, :type :ok, :f :append, :key "7", :value "x 5 3 y"} {:process 5, :type :invoke, :f :get, :key "4", :value nil} {:process 24, :type :ok, :f :get, :key "8", :value "x 41 6 yx 11 2 yx 3 6 yx 49 6 yx 24 16 yx 21 9 y"} {:process 24, :type :invoke, :f :append, :key "0", :value "x 24 20 y"} {:process 1, :type :ok, :f :get, :key "3", :value "x 21 4 yx 24 9 yx 31 0 yx 28 6 yx 5 2 yx 36 10 yx 41 8 yx 4 7 y"} {:process 1, :type :invoke, :f :get, :key "6", :value nil} {:process 15, :type :ok, :f :append, :key "8", :value "x 15 11 y"} {:process 15, :type :invoke, :f :get, :key "5", :value nil} {:process 38, :type :ok, :f :append, :key "8", :value "x 38 2 y"} {:process 38, :type :invoke, :f :get, :key "2", :value nil} {:process 21, :type :ok, :f :append, :key "1", :value "x 21 10 y"} {:process 21, :type :invoke, :f :append, :key "4", :value "x 21 11 y"} {:process 42, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 yx 45 2 yx 26 2 yx 45 4 yx 6 1 yx 7 1 yx 28 3 yx 28 4 yx 3 3 yx 30 4 yx 5 0 yx 45 12 yx 33 0 yx 33 1 yx 31 1 yx 42 4 yx 18 3 yx 16 2 yx 24 13 y"} {:process 42, :type :invoke, :f :append, :key "8", :value "x 42 5 y"} {:process 15, :type :ok, :f :get, :key "5", :value "x 15 6 yx 44 3 yx 41 0 yx 36 7 yx 17 3 yx 47 1 yx 45 2 yx 26 2 yx 45 4 yx 6 1 yx 7 1 yx 28 3 yx 28 4 yx 3 3 yx 30 4 yx 5 0 yx 45 12 yx 33 0 yx 33 1 yx 31 1 yx 42 4 yx 18 3 yx 16 2 yx 24 13 y"} {:process 15, :type :invoke, :f :append, :key "5", :value "x 15 12 y"} {:process 22, :type :ok, :f :append, :key "2", :value "x 22 8 y"} {:process 22, :type :invoke, :f :get, :key "0", :value nil} {:process 38, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 yx 22 8 yx 14 3 yx 17 8 yx 11 3 yx 17 12 yx 15 9 yx 0 2 y"} {:process 38, :type :invoke, :f :append, :key "6", :value "x 38 3 y"} {:process 1, :type :ok, :f :get, :key "6", :value "x 0 1 yx 6 4 yx 24 17 yx 45 19 yx 27 1 yx 15 10 y"} {:process 1, :type :invoke, :f :append, :key "6", :value "x 1 3 y"} {:process 24, :type :ok, :f :append, :key "0", :value "x 24 20 y"} {:process 24, :type :invoke, :f :append, :key "7", :value "x 24 21 y"} {:process 21, :type :ok, :f :append, :key "4", :value "x 21 11 y"} {:process 21, :type :invoke, :f :append, :key "2", :value "x 21 12 y"} {:process 1, :type :ok, :f :append, :key "6", :value "x 1 3 y"} {:process 1, :type :invoke, :f :append, :key "1", :value "x 1 4 y"} {:process 20, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 yx 22 8 yx 14 3 yx 17 8 yx 11 3 yx 17 12 yx 15 9 yx 0 2 y"} {:process 20, :type :invoke, :f :append, :key "0", :value "x 20 5 y"} {:process 15, :type :ok, :f :append, :key "5", :value "x 15 12 y"} {:process 15, :type :invoke, :f :append, :key "8", :value "x 15 13 y"} {:process 42, :type :ok, :f :append, :key "8", :value "x 42 5 y"} {:process 42, :type :invoke, :f :get, :key "7", :value nil} {:process 14, :type :ok, :f :append, :key "2", :value "x 14 3 y"} {:process 14, :type :invoke, :f :get, :key "8", :value nil} {:process 30, :type :ok, :f :append, :key "7", :value "x 30 5 y"} {:process 30, :type :invoke, :f :get, :key "1", :value nil} {:process 25, :type :ok, :f :append, :key "2", :value "x 25 3 y"} {:process 25, :type :invoke, :f :get, :key "5", :value nil} {:process 26, :type :ok, :f :append, :key "5", :value "x 26 2 y"} {:process 26, :type :invoke, :f :get, :key "9", :value nil} {:process 30, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 y"} {:process 30, :type :invoke, :f :append, :key "2", :value "x 30 6 y"} {:process 43, :type :ok, :f :get, :key "4", :value "x 1 2 yx 21 11 y"} {:process 43, :type :invoke, :f :get, :key "9", :value nil} {:process 14, :type :ok, :f :get, :key "8", :value "x 41 6 yx 11 2 yx 3 6 yx 49 6 yx 24 16 yx 21 9 yx 15 11 yx 38 2 yx 42 5 y"} {:process 14, :type :invoke, :f :append, :key "6", :value "x 14 4 y"} {:process 30, :type :ok, :f :append, :key "2", :value "x 30 6 y"} {:process 30, :type :invoke, :f :get, :key "7", :value nil} {:process 43, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 y"} {:process 43, :type :invoke, :f :get, :key "6", :value nil} {:process 26, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 y"} {:process 26, :type :invoke, :f :append, :key "3", :value "x 26 3 y"} {:process 14, :type :ok, :f :append, :key "6", :value "x 14 4 y"} {:process 14, :type :invoke, :f :get, :key "2", :value nil} {:process 26, :type :ok, :f :append, :key "3", :value "x 26 3 y"} {:process 26, :type :invoke, :f :put, :key "0", :value "x 26 4 y"} {:process 14, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 yx 22 8 yx 14 3 yx 17 8 yx 11 3 yx 17 12 yx 15 9 yx 0 2 yx 31 3 yx 25 3 yx 30 6 y"} {:process 14, :type :invoke, :f :put, :key "5", :value "x 14 5 y"} {:process 26, :type :ok, :f :put, :key "0", :value "x 26 4 y"} {:process 26, :type :invoke, :f :get, :key "8", :value nil} {:process 14, :type :ok, :f :put, :key "5", :value "x 14 5 y"} {:process 14, :type :invoke, :f :append, :key "7", :value "x 14 6 y"} {:process 26, :type :ok, :f :get, :key "8", :value "x 41 6 yx 11 2 yx 3 6 yx 49 6 yx 24 16 yx 21 9 yx 15 11 yx 38 2 yx 42 5 y"} {:process 26, :type :invoke, :f :append, :key "7", :value "x 26 5 y"} {:process 42, :type :ok, :f :get, :key "7", :value "x 24 14 yx 24 18 yx 5 3 yx 30 5 y"} {:process 42, :type :invoke, :f :get, :key "0", :value nil} {:process 14, :type :ok, :f :append, :key "7", :value "x 14 6 y"} {:process 14, :type :invoke, :f :append, :key "0", :value "x 14 7 y"} {:process 26, :type :ok, :f :append, :key "7", :value "x 26 5 y"} {:process 26, :type :invoke, :f :append, :key "1", :value "x 26 6 y"} {:process 14, :type :ok, :f :append, :key "0", :value "x 14 7 y"} {:process 14, :type :invoke, :f :append, :key "1", :value "x 14 8 y"} {:process 35, :type :ok, :f :append, :key "3", :value "x 35 1 y"} {:process 35, :type :invoke, :f :append, :key "7", :value "x 35 2 y"} {:process 31, :type :ok, :f :append, :key "2", :value "x 31 3 y"} {:process 31, :type :invoke, :f :get, :key "8", :value nil} {:process 23, :type :ok, :f :get, :key "7", :value "x 24 14 yx 24 18 yx 5 3 yx 30 5 yx 14 6 yx 26 5 y"} {:process 23, :type :invoke, :f :append, :key "3", :value "x 23 3 y"} {:process 47, :type :ok, :f :append, :key "1", :value "x 47 8 y"} {:process 47, :type :invoke, :f :get, :key "0", :value nil} {:process 38, :type :ok, :f :append, :key "6", :value "x 38 3 y"} {:process 38, :type :invoke, :f :append, :key "7", :value "x 38 4 y"} {:process 26, :type :ok, :f :append, :key "1", :value "x 26 6 y"} {:process 26, :type :invoke, :f :get, :key "1", :value nil} {:process 23, :type :ok, :f :append, :key "3", :value "x 23 3 y"} {:process 23, :type :invoke, :f :get, :key "6", :value nil} {:process 38, :type :ok, :f :append, :key "7", :value "x 38 4 y"} {:process 38, :type :invoke, :f :append, :key "5", :value "x 38 5 y"} {:process 23, :type :ok, :f :get, :key "6", :value "x 0 1 yx 6 4 yx 24 17 yx 45 19 yx 27 1 yx 15 10 yx 1 3 yx 38 3 yx 14 4 y"} {:process 23, :type :invoke, :f :append, :key "7", :value "x 23 4 y"} {:process 26, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 y"} {:process 26, :type :invoke, :f :get, :key "0", :value nil} {:process 47, :type :ok, :f :get, :key "0", :value "x 26 4 yx 14 7 y"} {:process 47, :type :invoke, :f :append, :key "1", :value "x 47 9 y"} {:process 38, :type :ok, :f :append, :key "5", :value "x 38 5 y"} {:process 38, :type :invoke, :f :append, :key "9", :value "x 38 6 y"} {:process 4, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 y"} {:process 4, :type :invoke, :f :get, :key "9", :value nil} {:process 47, :type :ok, :f :append, :key "1", :value "x 47 9 y"} {:process 47, :type :invoke, :f :append, :key "3", :value "x 47 10 y"} {:process 23, :type :ok, :f :append, :key "7", :value "x 23 4 y"} {:process 23, :type :invoke, :f :get, :key "0", :value nil} {:process 48, :type :ok, :f :append, :key "9", :value "x 48 2 y"} {:process 48, :type :invoke, :f :append, :key "4", :value "x 48 3 y"} {:process 26, :type :ok, :f :get, :key "0", :value "x 26 4 yx 14 7 y"} {:process 26, :type :invoke, :f :put, :key "4", :value "x 26 7 y"} {:process 4, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 y"} {:process 4, :type :invoke, :f :append, :key "6", :value "x 4 8 y"} {:process 23, :type :ok, :f :get, :key "0", :value "x 26 4 yx 14 7 y"} {:process 23, :type :invoke, :f :get, :key "1", :value nil} {:process 19, :type :ok, :f :get, :key "8", :value "x 41 6 yx 11 2 yx 3 6 yx 49 6 yx 24 16 yx 21 9 yx 15 11 yx 38 2 yx 42 5 y"} {:process 19, :type :invoke, :f :append, :key "3", :value "x 19 2 y"} {:process 38, :type :ok, :f :append, :key "9", :value "x 38 6 y"} {:process 38, :type :invoke, :f :append, :key "0", :value "x 38 7 y"} {:process 47, :type :ok, :f :append, :key "3", :value "x 47 10 y"} {:process 47, :type :invoke, :f :append, :key "5", :value "x 47 11 y"} {:process 48, :type :ok, :f :append, :key "4", :value "x 48 3 y"} {:process 48, :type :invoke, :f :append, :key "1", :value "x 48 4 y"} {:process 38, :type :ok, :f :append, :key "0", :value "x 38 7 y"} {:process 38, :type :invoke, :f :get, :key "0", :value nil} {:process 26, :type :ok, :f :put, :key "4", :value "x 26 7 y"} {:process 26, :type :invoke, :f :get, :key "6", :value nil} {:process 23, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 yx 47 9 y"} {:process 23, :type :invoke, :f :append, :key "2", :value "x 23 5 y"} {:process 19, :type :ok, :f :append, :key "3", :value "x 19 2 y"} {:process 19, :type :invoke, :f :append, :key "7", :value "x 19 3 y"} {:process 47, :type :ok, :f :append, :key "5", :value "x 47 11 y"} {:process 47, :type :invoke, :f :get, :key "0", :value nil} {:process 7, :type :ok, :f :get, :key "5", :value "x 14 5 yx 38 5 yx 39 2 yx 47 11 y"} {:process 38, :type :ok, :f :get, :key "0", :value "x 26 4 yx 14 7 yx 38 7 y"} {:process 7, :type :invoke, :f :get, :key "0", :value nil} {:process 38, :type :invoke, :f :append, :key "1", :value "x 38 8 y"} {:process 26, :type :ok, :f :get, :key "6", :value "x 0 1 yx 6 4 yx 24 17 yx 45 19 yx 27 1 yx 15 10 yx 1 3 yx 38 3 yx 14 4 y"} {:process 26, :type :invoke, :f :append, :key "0", :value "x 26 8 y"} {:process 47, :type :ok, :f :get, :key "0", :value "x 26 4 yx 14 7 yx 38 7 y"} {:process 2, :type :ok, :f :append, :key "0", :value "x 2 5 y"} {:process 2, :type :invoke, :f :append, :key "7", :value "x 2 6 y"} {:process 47, :type :invoke, :f :append, :key "8", :value "x 47 12 y"} {:process 26, :type :ok, :f :append, :key "0", :value "x 26 8 y"} {:process 26, :type :invoke, :f :get, :key "6", :value nil} {:process 19, :type :ok, :f :append, :key "7", :value "x 19 3 y"} {:process 19, :type :invoke, :f :get, :key "9", :value nil} {:process 47, :type :ok, :f :append, :key "8", :value "x 47 12 y"} {:process 7, :type :ok, :f :get, :key "0", :value "x 26 4 yx 14 7 yx 38 7 yx 2 5 yx 26 8 y"} {:process 47, :type :invoke, :f :put, :key "8", :value "x 47 13 y"} {:process 7, :type :invoke, :f :append, :key "7", :value "x 7 2 y"} {:process 19, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 yx 38 6 y"} {:process 19, :type :invoke, :f :get, :key "7", :value nil} {:process 38, :type :ok, :f :append, :key "1", :value "x 38 8 y"} {:process 38, :type :invoke, :f :get, :key "9", :value nil} {:process 41, :type :ok, :f :append, :key "6", :value "x 41 10 y"} {:process 41, :type :invoke, :f :get, :key "1", :value nil} {:process 47, :type :ok, :f :put, :key "8", :value "x 47 13 y"} {:process 47, :type :invoke, :f :append, :key "4", :value "x 47 14 y"} {:process 7, :type :ok, :f :append, :key "7", :value "x 7 2 y"} {:process 7, :type :invoke, :f :get, :key "7", :value nil} {:process 38, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 yx 38 6 y"} {:process 38, :type :invoke, :f :get, :key "2", :value nil} {:process 2, :type :ok, :f :append, :key "7", :value "x 2 6 y"} {:process 2, :type :invoke, :f :get, :key "0", :value nil} {:process 38, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 yx 22 8 yx 14 3 yx 17 8 yx 11 3 yx 17 12 yx 15 9 yx 0 2 yx 31 3 yx 25 3 yx 30 6 y"} {:process 38, :type :invoke, :f :get, :key "1", :value nil} {:process 38, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 yx 47 9 yx 38 8 y"} {:process 38, :type :invoke, :f :get, :key "0", :value nil} {:process 38, :type :ok, :f :get, :key "0", :value "x 26 4 yx 14 7 yx 38 7 yx 2 5 yx 26 8 y"} {:process 38, :type :invoke, :f :append, :key "7", :value "x 38 9 y"} {:process 38, :type :ok, :f :append, :key "7", :value "x 38 9 y"} {:process 38, :type :invoke, :f :append, :key "2", :value "x 38 10 y"} {:process 38, :type :ok, :f :append, :key "2", :value "x 38 10 y"} {:process 38, :type :invoke, :f :append, :key "6", :value "x 38 11 y"} {:process 12, :type :ok, :f :get, :key "6", :value "x 0 1 yx 6 4 yx 24 17 yx 45 19 yx 27 1 yx 15 10 yx 1 3 yx 38 3 yx 14 4 y"} {:process 12, :type :invoke, :f :get, :key "7", :value nil} {:process 38, :type :ok, :f :append, :key "6", :value "x 38 11 y"} {:process 38, :type :invoke, :f :get, :key "1", :value nil} {:process 38, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 yx 47 9 yx 38 8 y"} {:process 38, :type :invoke, :f :get, :key "9", :value nil} {:process 13, :type :ok, :f :append, :key "6", :value "x 13 1 y"} {:process 13, :type :invoke, :f :get, :key "1", :value nil} {:process 36, :type :ok, :f :append, :key "1", :value "x 36 11 y"} {:process 36, :type :invoke, :f :get, :key "8", :value nil} {:process 34, :type :ok, :f :get, :key "5", :value "x 14 5 yx 38 5 yx 39 2 yx 47 11 y"} {:process 34, :type :invoke, :f :get, :key "3", :value nil} {:process 38, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 yx 38 6 y"} {:process 38, :type :invoke, :f :append, :key "5", :value "x 38 12 y"} {:process 34, :type :ok, :f :get, :key "3", :value "x 44 11 yx 23 3 yx 47 10 yx 19 2 y"} {:process 34, :type :invoke, :f :get, :key "8", :value nil} {:process 13, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 yx 47 9 yx 38 8 y"} {:process 13, :type :invoke, :f :append, :key "7", :value "x 13 2 y"} {:process 38, :type :ok, :f :append, :key "5", :value "x 38 12 y"} {:process 38, :type :invoke, :f :get, :key "9", :value nil} {:process 18, :type :ok, :f :append, :key "6", :value "x 18 5 y"} {:process 18, :type :invoke, :f :get, :key "6", :value nil} {:process 34, :type :ok, :f :get, :key "8", :value "x 47 13 y"} {:process 34, :type :invoke, :f :get, :key "9", :value nil} {:process 32, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 y"} {:process 32, :type :invoke, :f :get, :key "7", :value nil} {:process 18, :type :ok, :f :get, :key "6", :value "x 0 1 yx 6 4 yx 24 17 yx 45 19 yx 27 1 yx 15 10 yx 1 3 yx 38 3 yx 14 4 yx 38 11 yx 18 5 y"} {:process 18, :type :invoke, :f :get, :key "3", :value nil} {:process 28, :type :ok, :f :append, :key "6", :value "x 28 8 y"} {:process 28, :type :invoke, :f :append, :key "7", :value "x 28 9 y"} {:process 34, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 yx 38 6 y"} {:process 34, :type :invoke, :f :append, :key "1", :value "x 34 2 y"} {:process 18, :type :ok, :f :get, :key "3", :value "x 44 11 yx 23 3 yx 47 10 yx 19 2 y"} {:process 18, :type :invoke, :f :get, :key "7", :value nil} {:process 28, :type :ok, :f :append, :key "7", :value "x 28 9 y"} {:process 28, :type :invoke, :f :append, :key "2", :value "x 28 10 y"} {:process 34, :type :ok, :f :append, :key "1", :value "x 34 2 y"} {:process 34, :type :invoke, :f :get, :key "4", :value nil} {:process 28, :type :ok, :f :append, :key "2", :value "x 28 10 y"} {:process 28, :type :invoke, :f :get, :key "9", :value nil} {:process 46, :type :ok, :f :append, :key "0", :value "x 46 3 y"} {:process 46, :type :invoke, :f :append, :key "0", :value "x 46 4 y"} {:process 34, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 y"} {:process 34, :type :invoke, :f :append, :key "7", :value "x 34 3 y"} {:process 28, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 yx 38 6 y"} {:process 28, :type :invoke, :f :get, :key "7", :value nil} {:process 46, :type :ok, :f :append, :key "0", :value "x 46 4 y"} {:process 46, :type :invoke, :f :get, :key "7", :value nil} {:process 28, :type :ok, :f :get, :key "7", :value "x 24 14 yx 24 18 yx 5 3 yx 30 5 yx 14 6 yx 26 5 yx 38 4 yx 35 2 yx 23 4 yx 19 3 yx 7 2 yx 2 6 yx 38 9 yx 13 2 yx 28 9 y"} {:process 28, :type :invoke, :f :get, :key "1", :value nil} {:process 3, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 yx 47 9 yx 38 8 yx 34 2 y"} {:process 3, :type :invoke, :f :get, :key "9", :value nil} {:process 34, :type :ok, :f :append, :key "7", :value "x 34 3 y"} {:process 34, :type :invoke, :f :append, :key "1", :value "x 34 4 y"} {:process 3, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 yx 38 6 y"} {:process 3, :type :invoke, :f :append, :key "8", :value "x 3 7 y"} {:process 34, :type :ok, :f :append, :key "1", :value "x 34 4 y"} {:process 34, :type :invoke, :f :get, :key "6", :value nil} {:process 46, :type :ok, :f :get, :key "7", :value "x 24 14 yx 24 18 yx 5 3 yx 30 5 yx 14 6 yx 26 5 yx 38 4 yx 35 2 yx 23 4 yx 19 3 yx 7 2 yx 2 6 yx 38 9 yx 13 2 yx 28 9 yx 34 3 y"} {:process 46, :type :invoke, :f :append, :key "6", :value "x 46 5 y"} {:process 6, :type :ok, :f :get, :key "6", :value "x 0 1 yx 6 4 yx 24 17 yx 45 19 yx 27 1 yx 15 10 yx 1 3 yx 38 3 yx 14 4 yx 38 11 yx 18 5 yx 28 8 y"} {:process 6, :type :invoke, :f :get, :key "2", :value nil} {:process 28, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 yx 47 9 yx 38 8 yx 34 2 yx 34 4 y"} {:process 28, :type :invoke, :f :get, :key "4", :value nil} {:process 45, :type :ok, :f :append, :key "6", :value "x 45 19 y"} {:process 45, :type :invoke, :f :get, :key "2", :value nil} {:process 9, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 yx 47 9 yx 38 8 yx 34 2 yx 34 4 y"} {:process 9, :type :invoke, :f :get, :key "4", :value nil} {:process 28, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 y"} {:process 28, :type :invoke, :f :append, :key "6", :value "x 28 11 y"} {:process 34, :type :ok, :f :get, :key "6", :value "x 0 1 yx 6 4 yx 24 17 yx 45 19 yx 27 1 yx 15 10 yx 1 3 yx 38 3 yx 14 4 yx 38 11 yx 18 5 yx 28 8 y"} {:process 34, :type :invoke, :f :get, :key "5", :value nil} {:process 6, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 yx 22 8 yx 14 3 yx 17 8 yx 11 3 yx 17 12 yx 15 9 yx 0 2 yx 31 3 yx 25 3 yx 30 6 yx 38 10 yx 28 10 y"} {:process 6, :type :invoke, :f :get, :key "3", :value nil} {:process 46, :type :ok, :f :append, :key "6", :value "x 46 5 y"} {:process 46, :type :invoke, :f :append, :key "3", :value "x 46 6 y"} {:process 45, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 yx 22 8 yx 14 3 yx 17 8 yx 11 3 yx 17 12 yx 15 9 yx 0 2 yx 31 3 yx 25 3 yx 30 6 yx 38 10 yx 28 10 y"} {:process 45, :type :invoke, :f :append, :key "3", :value "x 45 20 y"} {:process 9, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 y"} {:process 9, :type :invoke, :f :append, :key "2", :value "x 9 2 y"} {:process 28, :type :ok, :f :append, :key "6", :value "x 28 11 y"} {:process 28, :type :invoke, :f :append, :key "8", :value "x 28 12 y"} {:process 34, :type :ok, :f :get, :key "5", :value "x 14 5 yx 38 5 yx 39 2 yx 47 11 yx 38 12 y"} {:process 34, :type :invoke, :f :append, :key "2", :value "x 34 5 y"} {:process 28, :type :ok, :f :append, :key "8", :value "x 28 12 y"} {:process 28, :type :invoke, :f :append, :key "1", :value "x 28 13 y"} {:process 45, :type :ok, :f :append, :key "3", :value "x 45 20 y"} {:process 45, :type :invoke, :f :get, :key "8", :value nil} {:process 9, :type :ok, :f :append, :key "2", :value "x 9 2 y"} {:process 9, :type :invoke, :f :append, :key "9", :value "x 9 3 y"} {:process 11, :type :ok, :f :get, :key "8", :value "x 47 13 yx 28 12 y"} {:process 11, :type :invoke, :f :append, :key "9", :value "x 11 4 y"} {:process 46, :type :ok, :f :append, :key "3", :value "x 46 6 y"} {:process 46, :type :invoke, :f :get, :key "3", :value nil} {:process 28, :type :ok, :f :append, :key "1", :value "x 28 13 y"} {:process 28, :type :invoke, :f :get, :key "1", :value nil} {:process 45, :type :ok, :f :get, :key "8", :value "x 47 13 yx 28 12 y"} {:process 45, :type :invoke, :f :append, :key "8", :value "x 45 21 y"} {:process 10, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 yx 47 9 yx 38 8 yx 34 2 yx 34 4 yx 28 13 y"} {:process 10, :type :invoke, :f :get, :key "6", :value nil} {:process 17, :type :ok, :f :append, :key "2", :value "x 17 12 y"} {:process 17, :type :invoke, :f :get, :key "5", :value nil} {:process 9, :type :ok, :f :append, :key "9", :value "x 9 3 y"} {:process 9, :type :invoke, :f :append, :key "5", :value "x 9 4 y"} {:process 34, :type :ok, :f :append, :key "2", :value "x 34 5 y"} {:process 34, :type :invoke, :f :get, :key "1", :value nil} {:process 11, :type :ok, :f :append, :key "9", :value "x 11 4 y"} {:process 11, :type :invoke, :f :append, :key "8", :value "x 11 5 y"} {:process 10, :type :ok, :f :get, :key "6", :value "x 0 1 yx 6 4 yx 24 17 yx 45 19 yx 27 1 yx 15 10 yx 1 3 yx 38 3 yx 14 4 yx 38 11 yx 18 5 yx 28 8 yx 46 5 yx 28 11 y"} {:process 10, :type :invoke, :f :put, :key "3", :value "x 10 3 y"} {:process 17, :type :ok, :f :get, :key "5", :value "x 14 5 yx 38 5 yx 39 2 yx 47 11 yx 38 12 y"} {:process 17, :type :invoke, :f :get, :key "2", :value nil} {:process 28, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 yx 47 9 yx 38 8 yx 34 2 yx 34 4 yx 28 13 y"} {:process 28, :type :invoke, :f :append, :key "3", :value "x 28 14 y"} {:process 49, :type :ok, :f :get, :key "8", :value "x 47 13 yx 28 12 y"} {:process 49, :type :invoke, :f :get, :key "7", :value nil} {:process 40, :type :ok, :f :append, :key "8", :value "x 40 1 y"} {:process 40, :type :invoke, :f :get, :key "4", :value nil} {:process 9, :type :ok, :f :append, :key "5", :value "x 9 4 y"} {:process 9, :type :invoke, :f :append, :key "9", :value "x 9 5 y"} {:process 34, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 yx 47 9 yx 38 8 yx 34 2 yx 34 4 yx 28 13 y"} {:process 34, :type :invoke, :f :get, :key "5", :value nil} {:process 40, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 y"} {:process 40, :type :invoke, :f :put, :key "6", :value "x 40 2 y"} {:process 5, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 y"} {:process 0, :type :ok, :f :get, :key "0", :value "x 26 4 yx 14 7 yx 38 7 yx 2 5 yx 26 8 yx 46 4 y"} {:process 5, :type :invoke, :f :append, :key "3", :value "x 5 4 y"} {:process 0, :type :invoke, :f :append, :key "8", :value "x 0 3 y"} {:process 49, :type :ok, :f :get, :key "7", :value "x 24 14 yx 24 18 yx 5 3 yx 30 5 yx 14 6 yx 26 5 yx 38 4 yx 35 2 yx 23 4 yx 19 3 yx 7 2 yx 2 6 yx 38 9 yx 13 2 yx 28 9 yx 34 3 y"} {:process 49, :type :invoke, :f :append, :key "4", :value "x 49 7 y"} {:process 10, :type :ok, :f :put, :key "3", :value "x 10 3 y"} {:process 10, :type :invoke, :f :append, :key "0", :value "x 10 4 y"} {:process 28, :type :ok, :f :append, :key "3", :value "x 28 14 y"} {:process 28, :type :invoke, :f :put, :key "7", :value "x 28 15 y"} {:process 11, :type :ok, :f :append, :key "8", :value "x 11 5 y"} {:process 0, :type :ok, :f :append, :key "8", :value "x 0 3 y"} {:process 11, :type :invoke, :f :append, :key "0", :value "x 11 6 y"} {:process 0, :type :invoke, :f :append, :key "6", :value "x 0 4 y"} {:process 34, :type :ok, :f :get, :key "5", :value "x 14 5 yx 38 5 yx 39 2 yx 47 11 yx 38 12 yx 9 4 y"} {:process 34, :type :invoke, :f :get, :key "8", :value nil} {:process 0, :type :ok, :f :append, :key "6", :value "x 0 4 y"} {:process 0, :type :invoke, :f :get, :key "1", :value nil} {:process 5, :type :ok, :f :append, :key "3", :value "x 5 4 y"} {:process 5, :type :invoke, :f :append, :key "0", :value "x 5 5 y"} {:process 40, :type :ok, :f :put, :key "6", :value "x 40 2 y"} {:process 40, :type :invoke, :f :get, :key "0", :value nil} {:process 11, :type :ok, :f :append, :key "0", :value "x 11 6 y"} {:process 11, :type :invoke, :f :append, :key "9", :value "x 11 7 y"} {:process 28, :type :ok, :f :put, :key "7", :value "x 28 15 y"} {:process 28, :type :invoke, :f :put, :key "3", :value "x 28 16 y"} {:process 5, :type :ok, :f :append, :key "0", :value "x 5 5 y"} {:process 5, :type :invoke, :f :get, :key "4", :value nil} {:process 0, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 yx 47 9 yx 38 8 yx 34 2 yx 34 4 yx 28 13 y"} {:process 0, :type :invoke, :f :append, :key "4", :value "x 0 5 y"} {:process 28, :type :ok, :f :put, :key "3", :value "x 28 16 y"} {:process 28, :type :invoke, :f :get, :key "7", :value nil} {:process 1, :type :ok, :f :append, :key "1", :value "x 1 4 y"} {:process 1, :type :invoke, :f :get, :key "0", :value nil} {:process 0, :type :ok, :f :append, :key "4", :value "x 0 5 y"} {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 6 y"} {:process 15, :type :ok, :f :append, :key "8", :value "x 15 13 y"} {:process 15, :type :invoke, :f :get, :key "1", :value nil} {:process 20, :type :ok, :f :append, :key "0", :value "x 20 5 y"} {:process 20, :type :invoke, :f :append, :key "9", :value "x 20 6 y"} {:process 5, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 yx 49 7 yx 0 5 y"} {:process 5, :type :invoke, :f :get, :key "6", :value nil} {:process 28, :type :ok, :f :get, :key "7", :value "x 28 15 y"} {:process 28, :type :invoke, :f :get, :key "7", :value nil} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 6 y"} {:process 0, :type :invoke, :f :append, :key "1", :value "x 0 7 y"} {:process 1, :type :ok, :f :get, :key "0", :value "x 26 4 yx 14 7 yx 38 7 yx 2 5 yx 26 8 yx 46 4 yx 10 4 yx 11 6 yx 5 5 yx 20 5 yx 0 6 y"} {:process 1, :type :invoke, :f :append, :key "2", :value "x 1 5 y"} {:process 29, :type :ok, :f :append, :key "0", :value "x 29 0 y"} {:process 29, :type :invoke, :f :get, :key "2", :value nil} {:process 43, :type :ok, :f :get, :key "6", :value "x 40 2 y"} {:process 43, :type :invoke, :f :append, :key "6", :value "x 43 1 y"} {:process 44, :type :ok, :f :put, :key "3", :value "x 44 11 y"} {:process 44, :type :invoke, :f :append, :key "7", :value "x 44 12 y"} {:process 37, :type :ok, :f :append, :key "1", :value "x 37 2 y"} {:process 43, :type :ok, :f :append, :key "6", :value "x 43 1 y"} {:process 37, :type :invoke, :f :get, :key "0", :value nil} {:process 43, :type :invoke, :f :append, :key "0", :value "x 43 2 y"} {:process 8, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 yx 49 7 yx 0 5 y"} {:process 8, :type :invoke, :f :append, :key "3", :value "x 8 8 y"} {:process 44, :type :ok, :f :append, :key "7", :value "x 44 12 y"} {:process 44, :type :invoke, :f :append, :key "4", :value "x 44 13 y"} {:process 43, :type :ok, :f :append, :key "0", :value "x 43 2 y"} {:process 43, :type :invoke, :f :get, :key "0", :value nil} {:process 14, :type :ok, :f :append, :key "1", :value "x 14 8 y"} {:process 14, :type :invoke, :f :append, :key "2", :value "x 14 9 y"} {:process 37, :type :ok, :f :get, :key "0", :value "x 26 4 yx 14 7 yx 38 7 yx 2 5 yx 26 8 yx 46 4 yx 10 4 yx 11 6 yx 5 5 yx 20 5 yx 0 6 yx 43 2 y"} {:process 31, :type :ok, :f :get, :key "8", :value "x 47 13 yx 28 12 yx 0 3 yx 11 5 yx 15 13 y"} {:process 37, :type :invoke, :f :put, :key "6", :value "x 37 3 y"} {:process 31, :type :invoke, :f :append, :key "3", :value "x 31 4 y"} {:process 43, :type :ok, :f :get, :key "0", :value "x 26 4 yx 14 7 yx 38 7 yx 2 5 yx 26 8 yx 46 4 yx 10 4 yx 11 6 yx 5 5 yx 20 5 yx 0 6 yx 43 2 y"} {:process 43, :type :invoke, :f :append, :key "3", :value "x 43 3 y"} {:process 8, :type :ok, :f :append, :key "3", :value "x 8 8 y"} {:process 8, :type :invoke, :f :append, :key "2", :value "x 8 9 y"} {:process 35, :type :ok, :f :append, :key "7", :value "x 35 2 y"} {:process 35, :type :invoke, :f :get, :key "0", :value nil} {:process 31, :type :ok, :f :append, :key "3", :value "x 31 4 y"} {:process 39, :type :ok, :f :append, :key "5", :value "x 39 2 y"} {:process 31, :type :invoke, :f :get, :key "8", :value nil} {:process 39, :type :invoke, :f :put, :key "0", :value "x 39 3 y"} {:process 37, :type :ok, :f :put, :key "6", :value "x 37 3 y"} {:process 37, :type :invoke, :f :get, :key "4", :value nil} {:process 8, :type :ok, :f :append, :key "2", :value "x 8 9 y"} {:process 8, :type :invoke, :f :get, :key "0", :value nil} {:process 43, :type :ok, :f :append, :key "3", :value "x 43 3 y"} {:process 43, :type :invoke, :f :append, :key "3", :value "x 43 4 y"} {:process 14, :type :ok, :f :append, :key "2", :value "x 14 9 y"} {:process 14, :type :invoke, :f :get, :key "6", :value nil} {:process 37, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 yx 49 7 yx 0 5 yx 44 13 y"} {:process 37, :type :invoke, :f :append, :key "5", :value "x 37 4 y"} {:process 31, :type :ok, :f :get, :key "8", :value "x 47 13 yx 28 12 yx 0 3 yx 11 5 yx 15 13 y"} {:process 31, :type :invoke, :f :append, :key "8", :value "x 31 5 y"} {:process 39, :type :ok, :f :put, :key "0", :value "x 39 3 y"} {:process 39, :type :invoke, :f :put, :key "8", :value "x 39 4 y"} {:process 8, :type :ok, :f :get, :key "0", :value "x 39 3 y"} {:process 8, :type :invoke, :f :get, :key "8", :value nil} {:process 35, :type :ok, :f :get, :key "0", :value "x 39 3 y"} {:process 35, :type :invoke, :f :append, :key "0", :value "x 35 3 y"} {:process 4, :type :ok, :f :append, :key "6", :value "x 4 8 y"} {:process 4, :type :invoke, :f :append, :key "2", :value "x 4 9 y"} {:process 43, :type :ok, :f :append, :key "3", :value "x 43 4 y"} {:process 14, :type :ok, :f :get, :key "6", :value "x 37 3 yx 4 8 y"} {:process 43, :type :invoke, :f :get, :key "6", :value nil} {:process 48, :type :ok, :f :append, :key "1", :value "x 48 4 y"} {:process 14, :type :invoke, :f :put, :key "7", :value "x 14 10 y"} {:process 48, :type :invoke, :f :get, :key "8", :value nil} {:process 35, :type :ok, :f :append, :key "0", :value "x 35 3 y"} {:process 35, :type :invoke, :f :append, :key "3", :value "x 35 4 y"} {:process 31, :type :ok, :f :append, :key "8", :value "x 31 5 y"} {:process 31, :type :invoke, :f :append, :key "0", :value "x 31 6 y"} {:process 8, :type :ok, :f :get, :key "8", :value "x 47 13 yx 28 12 yx 0 3 yx 11 5 yx 15 13 yx 31 5 y"} {:process 8, :type :invoke, :f :get, :key "0", :value nil} {:process 43, :type :ok, :f :get, :key "6", :value "x 37 3 yx 4 8 y"} {:process 43, :type :invoke, :f :append, :key "6", :value "x 43 5 y"} {:process 14, :type :ok, :f :put, :key "7", :value "x 14 10 y"} {:process 14, :type :invoke, :f :append, :key "6", :value "x 14 11 y"} {:process 39, :type :ok, :f :put, :key "8", :value "x 39 4 y"} {:process 39, :type :invoke, :f :get, :key "2", :value nil} {:process 48, :type :ok, :f :get, :key "8", :value "x 39 4 y"} {:process 48, :type :invoke, :f :get, :key "6", :value nil} {:process 8, :type :ok, :f :get, :key "0", :value "x 39 3 yx 35 3 y"} {:process 35, :type :ok, :f :append, :key "3", :value "x 35 4 y"} {:process 8, :type :invoke, :f :append, :key "5", :value "x 8 10 y"} {:process 35, :type :invoke, :f :append, :key "0", :value "x 35 5 y"} {:process 39, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 yx 22 8 yx 14 3 yx 17 8 yx 11 3 yx 17 12 yx 15 9 yx 0 2 yx 31 3 yx 25 3 yx 30 6 yx 38 10 yx 28 10 yx 9 2 yx 34 5 yx 1 5 yx 8 9 yx 14 9 yx 4 9 y"} {:process 39, :type :invoke, :f :append, :key "5", :value "x 39 5 y"} {:process 43, :type :ok, :f :append, :key "6", :value "x 43 5 y"} {:process 43, :type :invoke, :f :get, :key "3", :value nil} {:process 26, :type :ok, :f :get, :key "6", :value "x 37 3 yx 4 8 yx 43 5 y"} {:process 26, :type :invoke, :f :get, :key "1", :value nil} {:process 48, :type :ok, :f :get, :key "6", :value "x 37 3 yx 4 8 yx 43 5 y"} {:process 48, :type :invoke, :f :get, :key "0", :value nil} {:process 35, :type :ok, :f :append, :key "0", :value "x 35 5 y"} {:process 35, :type :invoke, :f :get, :key "7", :value nil} {:process 14, :type :ok, :f :append, :key "6", :value "x 14 11 y"} {:process 14, :type :invoke, :f :get, :key "2", :value nil} {:process 39, :type :ok, :f :append, :key "5", :value "x 39 5 y"} {:process 39, :type :invoke, :f :append, :key "4", :value "x 39 6 y"} {:process 47, :type :ok, :f :append, :key "4", :value "x 47 14 y"} {:process 47, :type :invoke, :f :get, :key "6", :value nil} {:process 33, :type :ok, :f :append, :key "1", :value "x 33 2 y"} {:process 33, :type :invoke, :f :append, :key "1", :value "x 33 3 y"} {:process 2, :type :ok, :f :get, :key "0", :value "x 39 3 yx 35 3 yx 35 5 y"} {:process 2, :type :invoke, :f :append, :key "0", :value "x 2 7 y"} {:process 8, :type :ok, :f :append, :key "5", :value "x 8 10 y"} {:process 8, :type :invoke, :f :append, :key "9", :value "x 8 11 y"} {:process 35, :type :ok, :f :get, :key "7", :value "x 14 10 y"} {:process 35, :type :invoke, :f :append, :key "6", :value "x 35 6 y"} {:process 26, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 yx 47 9 yx 38 8 yx 34 2 yx 34 4 yx 28 13 yx 1 4 yx 48 4 y"} {:process 26, :type :invoke, :f :get, :key "3", :value nil} {:process 47, :type :ok, :f :get, :key "6", :value "x 37 3 yx 4 8 yx 43 5 yx 14 11 y"} {:process 47, :type :invoke, :f :append, :key "8", :value "x 47 15 y"} {:process 33, :type :ok, :f :append, :key "1", :value "x 33 3 y"} {:process 14, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 yx 22 8 yx 14 3 yx 17 8 yx 11 3 yx 17 12 yx 15 9 yx 0 2 yx 31 3 yx 25 3 yx 30 6 yx 38 10 yx 28 10 yx 9 2 yx 34 5 yx 1 5 yx 8 9 yx 14 9 yx 4 9 yx 23 5 y"} {:process 33, :type :invoke, :f :get, :key "2", :value nil} {:process 14, :type :invoke, :f :append, :key "5", :value "x 14 12 y"} {:process 47, :type :ok, :f :append, :key "8", :value "x 47 15 y"} {:process 47, :type :invoke, :f :get, :key "9", :value nil} {:process 8, :type :ok, :f :append, :key "9", :value "x 8 11 y"} {:process 8, :type :invoke, :f :append, :key "5", :value "x 8 12 y"} {:process 33, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 yx 22 8 yx 14 3 yx 17 8 yx 11 3 yx 17 12 yx 15 9 yx 0 2 yx 31 3 yx 25 3 yx 30 6 yx 38 10 yx 28 10 yx 9 2 yx 34 5 yx 1 5 yx 8 9 yx 14 9 yx 4 9 yx 23 5 y"} {:process 33, :type :invoke, :f :append, :key "9", :value "x 33 4 y"} {:process 35, :type :ok, :f :append, :key "6", :value "x 35 6 y"} {:process 35, :type :invoke, :f :get, :key "8", :value nil} {:process 14, :type :ok, :f :append, :key "5", :value "x 14 12 y"} {:process 14, :type :invoke, :f :get, :key "1", :value nil} {:process 47, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 yx 38 6 yx 9 3 yx 11 4 yx 9 5 yx 8 11 y"} {:process 47, :type :invoke, :f :get, :key "6", :value nil} {:process 33, :type :ok, :f :append, :key "9", :value "x 33 4 y"} {:process 33, :type :invoke, :f :get, :key "2", :value nil} {:process 8, :type :ok, :f :append, :key "5", :value "x 8 12 y"} {:process 8, :type :invoke, :f :get, :key "3", :value nil} {:process 35, :type :ok, :f :get, :key "8", :value "x 39 4 yx 47 15 y"} {:process 35, :type :invoke, :f :append, :key "5", :value "x 35 7 y"} {:process 47, :type :ok, :f :get, :key "6", :value "x 37 3 yx 4 8 yx 43 5 yx 14 11 yx 35 6 y"} {:process 47, :type :invoke, :f :get, :key "1", :value nil} {:process 8, :type :ok, :f :get, :key "3", :value "x 28 16 yx 8 8 yx 31 4 yx 43 3 yx 43 4 yx 35 4 y"} {:process 8, :type :invoke, :f :append, :key "3", :value "x 8 13 y"} {:process 35, :type :ok, :f :append, :key "5", :value "x 35 7 y"} {:process 35, :type :invoke, :f :put, :key "8", :value "x 35 8 y"} {:process 47, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 yx 47 9 yx 38 8 yx 34 2 yx 34 4 yx 28 13 yx 1 4 yx 48 4 yx 33 3 y"} {:process 47, :type :invoke, :f :get, :key "6", :value nil} {:process 33, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 yx 22 8 yx 14 3 yx 17 8 yx 11 3 yx 17 12 yx 15 9 yx 0 2 yx 31 3 yx 25 3 yx 30 6 yx 38 10 yx 28 10 yx 9 2 yx 34 5 yx 1 5 yx 8 9 yx 14 9 yx 4 9 yx 23 5 y"} {:process 33, :type :invoke, :f :get, :key "9", :value nil} {:process 8, :type :ok, :f :append, :key "3", :value "x 8 13 y"} {:process 8, :type :invoke, :f :get, :key "3", :value nil} {:process 16, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 yx 47 9 yx 38 8 yx 34 2 yx 34 4 yx 28 13 yx 1 4 yx 48 4 yx 33 3 y"} {:process 16, :type :invoke, :f :get, :key "6", :value nil} {:process 8, :type :ok, :f :get, :key "3", :value "x 28 16 yx 8 8 yx 31 4 yx 43 3 yx 43 4 yx 35 4 yx 8 13 y"} {:process 8, :type :invoke, :f :get, :key "2", :value nil} {:process 33, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 yx 38 6 yx 9 3 yx 11 4 yx 9 5 yx 8 11 yx 33 4 y"} {:process 33, :type :invoke, :f :get, :key "4", :value nil} {:process 35, :type :ok, :f :put, :key "8", :value "x 35 8 y"} {:process 35, :type :invoke, :f :get, :key "8", :value nil} {:process 16, :type :ok, :f :get, :key "6", :value "x 37 3 yx 4 8 yx 43 5 yx 14 11 yx 35 6 y"} {:process 16, :type :invoke, :f :append, :key "3", :value "x 16 3 y"} {:process 33, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 yx 49 7 yx 0 5 yx 44 13 y"} {:process 33, :type :invoke, :f :get, :key "0", :value nil} {:process 13, :type :ok, :f :append, :key "7", :value "x 13 2 y"} {:process 13, :type :invoke, :f :get, :key "4", :value nil} {:process 32, :type :ok, :f :get, :key "7", :value "x 14 10 y"} {:process 32, :type :invoke, :f :append, :key "1", :value "x 32 2 y"} {:process 8, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 yx 22 8 yx 14 3 yx 17 8 yx 11 3 yx 17 12 yx 15 9 yx 0 2 yx 31 3 yx 25 3 yx 30 6 yx 38 10 yx 28 10 yx 9 2 yx 34 5 yx 1 5 yx 8 9 yx 14 9 yx 4 9 yx 23 5 y"} {:process 8, :type :invoke, :f :append, :key "2", :value "x 8 14 y"} {:process 36, :type :ok, :f :get, :key "8", :value "x 35 8 y"} {:process 36, :type :invoke, :f :get, :key "8", :value nil} {:process 16, :type :ok, :f :append, :key "3", :value "x 16 3 y"} {:process 16, :type :invoke, :f :get, :key "5", :value nil} {:process 33, :type :ok, :f :get, :key "0", :value "x 39 3 yx 35 3 yx 35 5 yx 2 7 y"} {:process 33, :type :invoke, :f :get, :key "8", :value nil} {:process 16, :type :ok, :f :get, :key "5", :value "x 14 5 yx 38 5 yx 39 2 yx 47 11 yx 38 12 yx 9 4 yx 39 5 yx 8 10 yx 14 12 yx 8 12 yx 35 7 y"} {:process 16, :type :invoke, :f :append, :key "9", :value "x 16 4 y"} {:process 38, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 yx 38 6 yx 9 3 yx 11 4 yx 9 5 yx 8 11 yx 33 4 y"} {:process 38, :type :invoke, :f :append, :key "7", :value "x 38 13 y"} {:process 8, :type :ok, :f :append, :key "2", :value "x 8 14 y"} {:process 8, :type :invoke, :f :append, :key "1", :value "x 8 15 y"} {:process 32, :type :ok, :f :append, :key "1", :value "x 32 2 y"} {:process 32, :type :invoke, :f :get, :key "6", :value nil} {:process 16, :type :ok, :f :append, :key "9", :value "x 16 4 y"} {:process 16, :type :invoke, :f :append, :key "0", :value "x 16 5 y"} {:process 38, :type :ok, :f :append, :key "7", :value "x 38 13 y"} {:process 38, :type :invoke, :f :append, :key "9", :value "x 38 14 y"} {:process 8, :type :ok, :f :append, :key "1", :value "x 8 15 y"} {:process 8, :type :invoke, :f :append, :key "2", :value "x 8 16 y"} {:process 32, :type :ok, :f :get, :key "6", :value "x 37 3 yx 4 8 yx 43 5 yx 14 11 yx 35 6 y"} {:process 32, :type :invoke, :f :get, :key "2", :value nil} {:process 16, :type :ok, :f :append, :key "0", :value "x 16 5 y"} {:process 16, :type :invoke, :f :get, :key "7", :value nil} {:process 18, :type :ok, :f :get, :key "7", :value "x 14 10 yx 38 13 y"} {:process 18, :type :invoke, :f :get, :key "1", :value nil} {:process 38, :type :ok, :f :append, :key "9", :value "x 38 14 y"} {:process 38, :type :invoke, :f :append, :key "5", :value "x 38 15 y"} {:process 32, :type :ok, :f :get, :key "2", :value "x 18 5 yx 32 1 yx 24 5 yx 28 1 yx 44 1 yx 49 1 yx 44 9 yx 36 0 yx 4 0 yx 16 0 yx 41 5 yx 36 6 yx 17 2 yx 8 1 yx 47 0 yx 25 0 yx 24 8 yx 30 3 yx 22 2 yx 22 4 yx 45 13 yx 22 8 yx 14 3 yx 17 8 yx 11 3 yx 17 12 yx 15 9 yx 0 2 yx 31 3 yx 25 3 yx 30 6 yx 38 10 yx 28 10 yx 9 2 yx 34 5 yx 1 5 yx 8 9 yx 14 9 yx 4 9 yx 23 5 yx 8 14 yx 8 16 y"} {:process 32, :type :invoke, :f :append, :key "1", :value "x 32 3 y"} {:process 16, :type :ok, :f :get, :key "7", :value "x 14 10 yx 38 13 y"} {:process 16, :type :invoke, :f :append, :key "8", :value "x 16 6 y"} {:process 18, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 yx 47 9 yx 38 8 yx 34 2 yx 34 4 yx 28 13 yx 1 4 yx 48 4 yx 33 3 yx 32 2 yx 8 15 y"} {:process 18, :type :invoke, :f :append, :key "3", :value "x 18 6 y"} {:process 32, :type :ok, :f :append, :key "1", :value "x 32 3 y"} {:process 32, :type :invoke, :f :get, :key "7", :value nil} {:process 3, :type :ok, :f :append, :key "8", :value "x 3 7 y"} {:process 3, :type :invoke, :f :append, :key "3", :value "x 3 8 y"} {:process 16, :type :ok, :f :append, :key "8", :value "x 16 6 y"} {:process 16, :type :invoke, :f :append, :key "7", :value "x 16 7 y"} {:process 18, :type :ok, :f :append, :key "3", :value "x 18 6 y"} {:process 6, :type :ok, :f :get, :key "3", :value "x 28 16 yx 8 8 yx 31 4 yx 43 3 yx 43 4 yx 35 4 yx 8 13 yx 16 3 yx 18 6 y"} {:process 18, :type :invoke, :f :append, :key "2", :value "x 18 7 y"} {:process 6, :type :invoke, :f :put, :key "2", :value "x 6 5 y"} {:process 3, :type :ok, :f :append, :key "3", :value "x 3 8 y"} {:process 3, :type :invoke, :f :get, :key "8", :value nil} {:process 32, :type :ok, :f :get, :key "7", :value "x 14 10 yx 38 13 y"} {:process 32, :type :invoke, :f :get, :key "3", :value nil} {:process 6, :type :ok, :f :put, :key "2", :value "x 6 5 y"} {:process 6, :type :invoke, :f :append, :key "8", :value "x 6 6 y"} {:process 45, :type :ok, :f :append, :key "8", :value "x 45 21 y"} {:process 45, :type :invoke, :f :append, :key "6", :value "x 45 22 y"} {:process 16, :type :ok, :f :append, :key "7", :value "x 16 7 y"} {:process 16, :type :invoke, :f :append, :key "8", :value "x 16 8 y"} {:process 18, :type :ok, :f :append, :key "2", :value "x 18 7 y"} {:process 18, :type :invoke, :f :append, :key "2", :value "x 18 8 y"} {:process 32, :type :ok, :f :get, :key "3", :value "x 28 16 yx 8 8 yx 31 4 yx 43 3 yx 43 4 yx 35 4 yx 8 13 yx 16 3 yx 18 6 yx 3 8 y"} {:process 32, :type :invoke, :f :append, :key "3", :value "x 32 4 y"} {:process 6, :type :ok, :f :append, :key "8", :value "x 6 6 y"} {:process 6, :type :invoke, :f :get, :key "9", :value nil} {:process 45, :type :ok, :f :append, :key "6", :value "x 45 22 y"} {:process 45, :type :invoke, :f :get, :key "5", :value nil} {:process 16, :type :ok, :f :append, :key "8", :value "x 16 8 y"} {:process 16, :type :invoke, :f :put, :key "6", :value "x 16 9 y"} {:process 18, :type :ok, :f :append, :key "2", :value "x 18 8 y"} {:process 18, :type :invoke, :f :get, :key "8", :value nil} {:process 17, :type :ok, :f :get, :key "2", :value "x 6 5 yx 18 7 yx 18 8 y"} {:process 17, :type :invoke, :f :append, :key "3", :value "x 17 13 y"} {:process 45, :type :ok, :f :get, :key "5", :value "x 14 5 yx 38 5 yx 39 2 yx 47 11 yx 38 12 yx 9 4 yx 39 5 yx 8 10 yx 14 12 yx 8 12 yx 35 7 y"} {:process 45, :type :invoke, :f :append, :key "7", :value "x 45 23 y"} {:process 46, :type :ok, :f :get, :key "3", :value "x 28 16 yx 8 8 yx 31 4 yx 43 3 yx 43 4 yx 35 4 yx 8 13 yx 16 3 yx 18 6 yx 3 8 y"} {:process 46, :type :invoke, :f :append, :key "7", :value "x 46 7 y"} {:process 10, :type :ok, :f :append, :key "0", :value "x 10 4 y"} {:process 10, :type :invoke, :f :get, :key "3", :value nil} {:process 17, :type :ok, :f :append, :key "3", :value "x 17 13 y"} {:process 17, :type :invoke, :f :append, :key "6", :value "x 17 14 y"} {:process 6, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 yx 38 6 yx 9 3 yx 11 4 yx 9 5 yx 8 11 yx 33 4 yx 16 4 yx 38 14 y"} {:process 6, :type :invoke, :f :append, :key "5", :value "x 6 7 y"} {:process 45, :type :ok, :f :append, :key "7", :value "x 45 23 y"} {:process 45, :type :invoke, :f :append, :key "7", :value "x 45 24 y"} {:process 16, :type :ok, :f :put, :key "6", :value "x 16 9 y"} {:process 16, :type :invoke, :f :append, :key "1", :value "x 16 10 y"} {:process 18, :type :ok, :f :get, :key "8", :value "x 35 8 yx 16 6 yx 3 7 yx 45 21 yx 6 6 yx 16 8 y"} {:process 18, :type :invoke, :f :append, :key "3", :value "x 18 9 y"} {:process 17, :type :ok, :f :append, :key "6", :value "x 17 14 y"} {:process 17, :type :invoke, :f :append, :key "1", :value "x 17 15 y"} {:process 34, :type :ok, :f :get, :key "8", :value "x 35 8 yx 16 6 yx 3 7 yx 45 21 yx 6 6 yx 16 8 y"} {:process 34, :type :invoke, :f :append, :key "2", :value "x 34 6 y"} {:process 40, :type :ok, :f :get, :key "0", :value "x 39 3 yx 35 3 yx 35 5 yx 2 7 yx 16 5 y"} {:process 40, :type :invoke, :f :append, :key "0", :value "x 40 3 y"} {:process 10, :type :ok, :f :get, :key "3", :value "x 28 16 yx 8 8 yx 31 4 yx 43 3 yx 43 4 yx 35 4 yx 8 13 yx 16 3 yx 18 6 yx 3 8 yx 17 13 y"} {:process 10, :type :invoke, :f :append, :key "8", :value "x 10 5 y"} {:process 6, :type :ok, :f :append, :key "5", :value "x 6 7 y"} {:process 6, :type :invoke, :f :get, :key "7", :value nil} {:process 9, :type :ok, :f :append, :key "9", :value "x 9 5 y"} {:process 9, :type :invoke, :f :append, :key "8", :value "x 9 6 y"} {:process 45, :type :ok, :f :append, :key "7", :value "x 45 24 y"} {:process 45, :type :invoke, :f :get, :key "4", :value nil} {:process 46, :type :ok, :f :append, :key "7", :value "x 46 7 y"} {:process 46, :type :invoke, :f :append, :key "0", :value "x 46 8 y"} {:process 16, :type :ok, :f :append, :key "1", :value "x 16 10 y"} {:process 16, :type :invoke, :f :get, :key "3", :value nil} {:process 34, :type :ok, :f :append, :key "2", :value "x 34 6 y"} {:process 27, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 yx 38 6 yx 9 3 yx 11 4 yx 9 5 yx 8 11 yx 33 4 yx 16 4 yx 38 14 yx 11 7 y"} {:process 34, :type :invoke, :f :get, :key "0", :value nil} {:process 27, :type :invoke, :f :append, :key "1", :value "x 27 2 y"} {:process 40, :type :ok, :f :append, :key "0", :value "x 40 3 y"} {:process 40, :type :invoke, :f :get, :key "7", :value nil} {:process 11, :type :ok, :f :append, :key "9", :value "x 11 7 y"} {:process 11, :type :invoke, :f :get, :key "5", :value nil} {:process 18, :type :ok, :f :append, :key "3", :value "x 18 9 y"} {:process 18, :type :invoke, :f :append, :key "5", :value "x 18 10 y"} {:process 45, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 yx 49 7 yx 0 5 yx 44 13 y"} {:process 45, :type :invoke, :f :get, :key "4", :value nil} {:process 9, :type :ok, :f :append, :key "8", :value "x 9 6 y"} {:process 15, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 yx 47 9 yx 38 8 yx 34 2 yx 34 4 yx 28 13 yx 1 4 yx 48 4 yx 33 3 yx 32 2 yx 8 15 yx 32 3 yx 16 10 y"} {:process 15, :type :invoke, :f :append, :key "5", :value "x 15 14 y"} {:process 9, :type :invoke, :f :get, :key "9", :value nil} {:process 6, :type :ok, :f :get, :key "7", :value "x 14 10 yx 38 13 yx 16 7 yx 45 23 yx 46 7 yx 45 24 y"} {:process 6, :type :invoke, :f :append, :key "8", :value "x 6 8 y"} {:process 16, :type :ok, :f :get, :key "3", :value "x 28 16 yx 8 8 yx 31 4 yx 43 3 yx 43 4 yx 35 4 yx 8 13 yx 16 3 yx 18 6 yx 3 8 yx 17 13 yx 18 9 y"} {:process 16, :type :invoke, :f :append, :key "3", :value "x 16 11 y"} {:process 11, :type :ok, :f :get, :key "5", :value "x 14 5 yx 38 5 yx 39 2 yx 47 11 yx 38 12 yx 9 4 yx 39 5 yx 8 10 yx 14 12 yx 8 12 yx 35 7 yx 6 7 y"} {:process 11, :type :invoke, :f :get, :key "1", :value nil} {:process 34, :type :ok, :f :get, :key "0", :value "x 39 3 yx 35 3 yx 35 5 yx 2 7 yx 16 5 yx 40 3 yx 46 8 y"} {:process 34, :type :invoke, :f :append, :key "2", :value "x 34 7 y"} {:process 18, :type :ok, :f :append, :key "5", :value "x 18 10 y"} {:process 18, :type :invoke, :f :get, :key "6", :value nil} {:process 15, :type :ok, :f :append, :key "5", :value "x 15 14 y"} {:process 9, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 yx 38 6 yx 9 3 yx 11 4 yx 9 5 yx 8 11 yx 33 4 yx 16 4 yx 38 14 yx 11 7 y"} {:process 9, :type :invoke, :f :append, :key "7", :value "x 9 7 y"} {:process 15, :type :invoke, :f :get, :key "1", :value nil} {:process 6, :type :ok, :f :append, :key "8", :value "x 6 8 y"} {:process 11, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 yx 47 9 yx 38 8 yx 34 2 yx 34 4 yx 28 13 yx 1 4 yx 48 4 yx 33 3 yx 32 2 yx 8 15 yx 32 3 yx 16 10 y"} {:process 40, :type :ok, :f :get, :key "7", :value "x 14 10 yx 38 13 yx 16 7 yx 45 23 yx 46 7 yx 45 24 y"} {:process 11, :type :invoke, :f :get, :key "5", :value nil} {:process 6, :type :invoke, :f :append, :key "7", :value "x 6 9 y"} {:process 40, :type :invoke, :f :put, :key "6", :value "x 40 4 y"} {:process 34, :type :ok, :f :append, :key "2", :value "x 34 7 y"} {:process 34, :type :invoke, :f :append, :key "8", :value "x 34 8 y"} {:process 27, :type :ok, :f :append, :key "1", :value "x 27 2 y"} {:process 27, :type :invoke, :f :append, :key "7", :value "x 27 3 y"} {:process 29, :type :ok, :f :get, :key "2", :value "x 6 5 yx 18 7 yx 18 8 yx 34 6 yx 34 7 y"} {:process 20, :type :ok, :f :append, :key "9", :value "x 20 6 y"} {:process 29, :type :invoke, :f :get, :key "4", :value nil} {:process 20, :type :invoke, :f :append, :key "1", :value "x 20 7 y"} {:process 9, :type :ok, :f :append, :key "7", :value "x 9 7 y"} {:process 9, :type :invoke, :f :append, :key "4", :value "x 9 8 y"} {:process 6, :type :ok, :f :append, :key "7", :value "x 6 9 y"} {:process 6, :type :invoke, :f :append, :key "5", :value "x 6 10 y"} {:process 11, :type :ok, :f :get, :key "5", :value "x 14 5 yx 38 5 yx 39 2 yx 47 11 yx 38 12 yx 9 4 yx 39 5 yx 8 10 yx 14 12 yx 8 12 yx 35 7 yx 6 7 yx 18 10 yx 15 14 y"} {:process 11, :type :invoke, :f :get, :key "1", :value nil} {:process 40, :type :ok, :f :put, :key "6", :value "x 40 4 y"} {:process 40, :type :invoke, :f :get, :key "2", :value nil} {:process 34, :type :ok, :f :append, :key "8", :value "x 34 8 y"} {:process 34, :type :invoke, :f :append, :key "7", :value "x 34 9 y"} {:process 29, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 yx 49 7 yx 0 5 yx 44 13 yx 9 8 y"} {:process 29, :type :invoke, :f :get, :key "0", :value nil} {:process 40, :type :ok, :f :get, :key "2", :value "x 6 5 yx 18 7 yx 18 8 yx 34 6 yx 34 7 y"} {:process 40, :type :invoke, :f :get, :key "9", :value nil} {:process 0, :type :ok, :f :append, :key "1", :value "x 0 7 y"} {:process 0, :type :invoke, :f :append, :key "6", :value "x 0 8 y"} {:process 29, :type :ok, :f :get, :key "0", :value "x 39 3 yx 35 3 yx 35 5 yx 2 7 yx 16 5 yx 40 3 yx 46 8 y"} {:process 11, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 yx 47 9 yx 38 8 yx 34 2 yx 34 4 yx 28 13 yx 1 4 yx 48 4 yx 33 3 yx 32 2 yx 8 15 yx 32 3 yx 16 10 yx 27 2 yx 0 7 y"} {:process 29, :type :invoke, :f :append, :key "1", :value "x 29 1 y"} {:process 11, :type :invoke, :f :get, :key "2", :value nil} {:process 6, :type :ok, :f :append, :key "5", :value "x 6 10 y"} {:process 6, :type :invoke, :f :append, :key "4", :value "x 6 11 y"} {:process 34, :type :ok, :f :append, :key "7", :value "x 34 9 y"} {:process 34, :type :invoke, :f :append, :key "9", :value "x 34 10 y"} {:process 0, :type :ok, :f :append, :key "6", :value "x 0 8 y"} {:process 0, :type :invoke, :f :append, :key "0", :value "x 0 9 y"} {:process 29, :type :ok, :f :append, :key "1", :value "x 29 1 y"} {:process 29, :type :invoke, :f :append, :key "2", :value "x 29 2 y"} {:process 11, :type :ok, :f :get, :key "2", :value "x 6 5 yx 18 7 yx 18 8 yx 34 6 yx 34 7 y"} {:process 11, :type :invoke, :f :get, :key "2", :value nil} {:process 1, :type :ok, :f :append, :key "2", :value "x 1 5 y"} {:process 1, :type :invoke, :f :append, :key "4", :value "x 1 6 y"} {:process 22, :type :ok, :f :get, :key "0", :value "x 39 3 yx 35 3 yx 35 5 yx 2 7 yx 16 5 yx 40 3 yx 46 8 y"} {:process 22, :type :invoke, :f :append, :key "2", :value "x 22 9 y"} {:process 24, :type :ok, :f :append, :key "7", :value "x 24 21 y"} {:process 24, :type :invoke, :f :append, :key "7", :value "x 24 22 y"} {:process 1, :type :ok, :f :append, :key "4", :value "x 1 6 y"} {:process 1, :type :invoke, :f :append, :key "2", :value "x 1 7 y"} {:process 6, :type :ok, :f :append, :key "4", :value "x 6 11 y"} {:process 6, :type :invoke, :f :get, :key "0", :value nil} {:process 25, :type :ok, :f :get, :key "5", :value "x 14 5 yx 38 5 yx 39 2 yx 47 11 yx 38 12 yx 9 4 yx 39 5 yx 8 10 yx 14 12 yx 8 12 yx 35 7 yx 6 7 yx 18 10 yx 15 14 yx 6 10 y"} {:process 25, :type :invoke, :f :append, :key "5", :value "x 25 4 y"} {:process 24, :type :ok, :f :append, :key "7", :value "x 24 22 y"} {:process 24, :type :invoke, :f :get, :key "1", :value nil} {:process 0, :type :ok, :f :append, :key "0", :value "x 0 9 y"} {:process 0, :type :invoke, :f :get, :key "4", :value nil} {:process 22, :type :ok, :f :append, :key "2", :value "x 22 9 y"} {:process 22, :type :invoke, :f :get, :key "8", :value nil} {:process 1, :type :ok, :f :append, :key "2", :value "x 1 7 y"} {:process 1, :type :invoke, :f :append, :key "5", :value "x 1 8 y"} {:process 25, :type :ok, :f :append, :key "5", :value "x 25 4 y"} {:process 25, :type :invoke, :f :get, :key "4", :value nil} {:process 0, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 yx 49 7 yx 0 5 yx 44 13 yx 9 8 yx 1 6 yx 6 11 y"} {:process 0, :type :invoke, :f :append, :key "4", :value "x 0 10 y"} {:process 6, :type :ok, :f :get, :key "0", :value "x 39 3 yx 35 3 yx 35 5 yx 2 7 yx 16 5 yx 40 3 yx 46 8 yx 0 9 y"} {:process 6, :type :invoke, :f :append, :key "8", :value "x 6 12 y"} {:process 24, :type :ok, :f :get, :key "1", :value "x 47 7 yx 23 0 yx 25 2 yx 6 3 yx 40 0 yx 37 2 yx 20 3 yx 42 2 yx 33 2 yx 18 2 yx 4 4 yx 36 11 yx 17 7 yx 28 7 yx 45 15 yx 17 10 yx 21 10 yx 26 6 yx 47 8 yx 14 8 yx 47 9 yx 38 8 yx 34 2 yx 34 4 yx 28 13 yx 1 4 yx 48 4 yx 33 3 yx 32 2 yx 8 15 yx 32 3 yx 16 10 yx 27 2 yx 0 7 yx 29 1 y"} {:process 24, :type :invoke, :f :get, :key "3", :value nil} {:process 25, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 yx 49 7 yx 0 5 yx 44 13 yx 9 8 yx 1 6 yx 6 11 y"} {:process 25, :type :invoke, :f :append, :key "6", :value "x 25 5 y"} {:process 6, :type :ok, :f :append, :key "8", :value "x 6 12 y"} {:process 6, :type :invoke, :f :put, :key "1", :value "x 6 13 y"} {:process 1, :type :ok, :f :append, :key "5", :value "x 1 8 y"} {:process 1, :type :invoke, :f :append, :key "9", :value "x 1 9 y"} {:process 25, :type :ok, :f :append, :key "6", :value "x 25 5 y"} {:process 25, :type :invoke, :f :append, :key "7", :value "x 25 6 y"} {:process 25, :type :ok, :f :append, :key "7", :value "x 25 6 y"} {:process 25, :type :invoke, :f :append, :key "6", :value "x 25 7 y"} {:process 1, :type :ok, :f :append, :key "9", :value "x 1 9 y"} {:process 1, :type :invoke, :f :append, :key "9", :value "x 1 10 y"} {:process 25, :type :ok, :f :append, :key "6", :value "x 25 7 y"} {:process 25, :type :invoke, :f :get, :key "8", :value nil} {:process 25, :type :ok, :f :get, :key "8", :value "x 35 8 yx 16 6 yx 3 7 yx 45 21 yx 6 6 yx 16 8 yx 9 6 yx 6 8 yx 34 8 yx 6 12 y"} {:process 25, :type :invoke, :f :append, :key "4", :value "x 25 8 y"} {:process 1, :type :ok, :f :append, :key "9", :value "x 1 10 y"} {:process 1, :type :invoke, :f :append, :key "7", :value "x 1 11 y"} {:process 25, :type :ok, :f :append, :key "4", :value "x 25 8 y"} {:process 25, :type :invoke, :f :get, :key "1", :value nil} {:process 1, :type :ok, :f :append, :key "7", :value "x 1 11 y"} {:process 1, :type :invoke, :f :get, :key "3", :value nil} {:process 25, :type :ok, :f :get, :key "1", :value "x 6 13 y"} {:process 25, :type :invoke, :f :get, :key "7", :value nil} {:process 25, :type :ok, :f :get, :key "7", :value "x 14 10 yx 38 13 yx 16 7 yx 45 23 yx 46 7 yx 45 24 yx 9 7 yx 6 9 yx 34 9 yx 24 22 yx 25 6 yx 1 11 y"} {:process 25, :type :invoke, :f :append, :key "7", :value "x 25 9 y"} {:process 1, :type :ok, :f :get, :key "3", :value "x 28 16 yx 8 8 yx 31 4 yx 43 3 yx 43 4 yx 35 4 yx 8 13 yx 16 3 yx 18 6 yx 3 8 yx 17 13 yx 18 9 y"} {:process 1, :type :invoke, :f :append, :key "8", :value "x 1 12 y"} {:process 42, :type :ok, :f :get, :key "0", :value "x 39 3 yx 35 3 yx 35 5 yx 2 7 yx 16 5 yx 40 3 yx 46 8 yx 0 9 y"} {:process 42, :type :invoke, :f :append, :key "7", :value "x 42 6 y"} {:process 1, :type :ok, :f :append, :key "8", :value "x 1 12 y"} {:process 1, :type :invoke, :f :append, :key "2", :value "x 1 13 y"} {:process 25, :type :ok, :f :append, :key "7", :value "x 25 9 y"} {:process 25, :type :invoke, :f :put, :key "0", :value "x 25 10 y"} {:process 25, :type :ok, :f :put, :key "0", :value "x 25 10 y"} {:process 25, :type :invoke, :f :get, :key "0", :value nil} {:process 42, :type :ok, :f :append, :key "7", :value "x 42 6 y"} {:process 42, :type :invoke, :f :append, :key "2", :value "x 42 7 y"} {:process 44, :type :ok, :f :append, :key "4", :value "x 44 13 y"} {:process 44, :type :invoke, :f :get, :key "4", :value nil} {:process 25, :type :ok, :f :get, :key "0", :value "x 25 10 y"} {:process 25, :type :invoke, :f :append, :key "5", :value "x 25 11 y"} {:process 42, :type :ok, :f :append, :key "2", :value "x 42 7 y"} {:process 42, :type :invoke, :f :get, :key "1", :value nil} {:process 42, :type :ok, :f :get, :key "1", :value "x 6 13 y"} {:process 42, :type :invoke, :f :get, :key "1", :value nil} {:process 44, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 yx 49 7 yx 0 5 yx 44 13 yx 9 8 yx 1 6 yx 6 11 yx 25 8 y"} {:process 44, :type :invoke, :f :append, :key "3", :value "x 44 14 y"} {:process 42, :type :ok, :f :get, :key "1", :value "x 6 13 y"} {:process 42, :type :invoke, :f :append, :key "4", :value "x 42 8 y"} {:process 42, :type :ok, :f :append, :key "4", :value "x 42 8 y"} {:process 42, :type :invoke, :f :put, :key "0", :value "x 42 9 y"} {:process 44, :type :ok, :f :append, :key "3", :value "x 44 14 y"} {:process 44, :type :invoke, :f :append, :key "6", :value "x 44 15 y"} {:process 19, :type :ok, :f :get, :key "7", :value "x 14 10 yx 38 13 yx 16 7 yx 45 23 yx 46 7 yx 45 24 yx 9 7 yx 6 9 yx 34 9 yx 24 22 yx 25 6 yx 1 11 yx 25 9 yx 42 6 y"} {:process 19, :type :invoke, :f :append, :key "2", :value "x 19 4 y"} {:process 37, :type :ok, :f :append, :key "5", :value "x 37 4 y"} {:process 37, :type :invoke, :f :append, :key "0", :value "x 37 5 y"} {:process 42, :type :ok, :f :put, :key "0", :value "x 42 9 y"} {:process 42, :type :invoke, :f :get, :key "9", :value nil} {:process 7, :type :ok, :f :get, :key "7", :value "x 14 10 yx 38 13 yx 16 7 yx 45 23 yx 46 7 yx 45 24 yx 9 7 yx 6 9 yx 34 9 yx 24 22 yx 25 6 yx 1 11 yx 25 9 yx 42 6 y"} {:process 7, :type :invoke, :f :append, :key "5", :value "x 7 3 y"} {:process 31, :type :ok, :f :append, :key "0", :value "x 31 6 y"} {:process 31, :type :invoke, :f :append, :key "6", :value "x 31 7 y"} {:process 44, :type :ok, :f :append, :key "6", :value "x 44 15 y"} {:process 44, :type :invoke, :f :append, :key "1", :value "x 44 16 y"} {:process 7, :type :ok, :f :append, :key "5", :value "x 7 3 y"} {:process 7, :type :invoke, :f :append, :key "5", :value "x 7 4 y"} {:process 42, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 yx 38 6 yx 9 3 yx 11 4 yx 9 5 yx 8 11 yx 33 4 yx 16 4 yx 38 14 yx 11 7 yx 20 6 yx 1 9 yx 1 10 y"} {:process 42, :type :invoke, :f :append, :key "7", :value "x 42 10 y"} {:process 4, :type :ok, :f :append, :key "2", :value "x 4 9 y"} {:process 4, :type :invoke, :f :append, :key "7", :value "x 4 10 y"} {:process 19, :type :ok, :f :append, :key "2", :value "x 19 4 y"} {:process 19, :type :invoke, :f :get, :key "9", :value nil} {:process 4, :type :ok, :f :append, :key "7", :value "x 4 10 y"} {:process 4, :type :invoke, :f :get, :key "9", :value nil} {:process 31, :type :ok, :f :append, :key "6", :value "x 31 7 y"} {:process 31, :type :invoke, :f :append, :key "1", :value "x 31 8 y"} {:process 39, :type :ok, :f :append, :key "4", :value "x 39 6 y"} {:process 39, :type :invoke, :f :append, :key "4", :value "x 39 7 y"} {:process 23, :type :ok, :f :append, :key "2", :value "x 23 5 y"} {:process 23, :type :invoke, :f :get, :key "1", :value nil} {:process 19, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 yx 38 6 yx 9 3 yx 11 4 yx 9 5 yx 8 11 yx 33 4 yx 16 4 yx 38 14 yx 11 7 yx 20 6 yx 1 9 yx 1 10 y"} {:process 19, :type :invoke, :f :get, :key "0", :value nil} {:process 7, :type :ok, :f :append, :key "5", :value "x 7 4 y"} {:process 7, :type :invoke, :f :append, :key "2", :value "x 7 5 y"} {:process 4, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 yx 38 6 yx 9 3 yx 11 4 yx 9 5 yx 8 11 yx 33 4 yx 16 4 yx 38 14 yx 11 7 yx 20 6 yx 1 9 yx 1 10 y"} {:process 4, :type :invoke, :f :append, :key "8", :value "x 4 11 y"} {:process 42, :type :ok, :f :append, :key "7", :value "x 42 10 y"} {:process 42, :type :invoke, :f :append, :key "4", :value "x 42 11 y"} {:process 31, :type :ok, :f :append, :key "1", :value "x 31 8 y"} {:process 31, :type :invoke, :f :append, :key "4", :value "x 31 9 y"} {:process 41, :type :ok, :f :get, :key "1", :value "x 6 13 yx 31 8 y"} {:process 41, :type :invoke, :f :get, :key "1", :value nil} {:process 39, :type :ok, :f :append, :key "4", :value "x 39 7 y"} {:process 39, :type :invoke, :f :get, :key "8", :value nil} {:process 31, :type :ok, :f :append, :key "4", :value "x 31 9 y"} {:process 31, :type :invoke, :f :get, :key "4", :value nil} {:process 41, :type :ok, :f :get, :key "1", :value "x 6 13 yx 31 8 y"} {:process 41, :type :invoke, :f :get, :key "6", :value nil} {:process 42, :type :ok, :f :append, :key "4", :value "x 42 11 y"} {:process 42, :type :invoke, :f :append, :key "1", :value "x 42 12 y"} {:process 23, :type :ok, :f :get, :key "1", :value "x 6 13 yx 31 8 y"} {:process 23, :type :invoke, :f :append, :key "2", :value "x 23 6 y"} {:process 4, :type :ok, :f :append, :key "8", :value "x 4 11 y"} {:process 4, :type :invoke, :f :get, :key "8", :value nil} {:process 39, :type :ok, :f :get, :key "8", :value "x 35 8 yx 16 6 yx 3 7 yx 45 21 yx 6 6 yx 16 8 yx 9 6 yx 6 8 yx 34 8 yx 6 12 yx 1 12 yx 4 11 y"} {:process 39, :type :invoke, :f :get, :key "5", :value nil} {:process 31, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 yx 49 7 yx 0 5 yx 44 13 yx 9 8 yx 1 6 yx 6 11 yx 25 8 yx 42 8 yx 39 6 yx 39 7 yx 31 9 yx 42 11 y"} {:process 31, :type :invoke, :f :get, :key "7", :value nil} {:process 2, :type :ok, :f :append, :key "0", :value "x 2 7 y"} {:process 2, :type :invoke, :f :append, :key "7", :value "x 2 8 y"} {:process 41, :type :ok, :f :get, :key "6", :value "x 40 4 yx 0 8 yx 25 5 yx 25 7 yx 44 15 yx 31 7 y"} {:process 41, :type :invoke, :f :get, :key "3", :value nil} {:process 23, :type :ok, :f :append, :key "2", :value "x 23 6 y"} {:process 23, :type :invoke, :f :append, :key "9", :value "x 23 7 y"} {:process 4, :type :ok, :f :get, :key "8", :value "x 35 8 yx 16 6 yx 3 7 yx 45 21 yx 6 6 yx 16 8 yx 9 6 yx 6 8 yx 34 8 yx 6 12 yx 1 12 yx 4 11 y"} {:process 4, :type :invoke, :f :append, :key "5", :value "x 4 12 y"} {:process 4, :type :ok, :f :append, :key "5", :value "x 4 12 y"} {:process 4, :type :invoke, :f :append, :key "3", :value "x 4 13 y"} {:process 2, :type :ok, :f :append, :key "7", :value "x 2 8 y"} {:process 2, :type :invoke, :f :get, :key "5", :value nil} {:process 23, :type :ok, :f :append, :key "9", :value "x 23 7 y"} {:process 23, :type :invoke, :f :append, :key "5", :value "x 23 8 y"} {:process 31, :type :ok, :f :get, :key "7", :value "x 14 10 yx 38 13 yx 16 7 yx 45 23 yx 46 7 yx 45 24 yx 9 7 yx 6 9 yx 34 9 yx 24 22 yx 25 6 yx 1 11 yx 25 9 yx 42 6 yx 4 10 yx 42 10 yx 2 8 y"} {:process 31, :type :invoke, :f :get, :key "8", :value nil} {:process 41, :type :ok, :f :get, :key "3", :value "x 28 16 yx 8 8 yx 31 4 yx 43 3 yx 43 4 yx 35 4 yx 8 13 yx 16 3 yx 18 6 yx 3 8 yx 17 13 yx 18 9 yx 44 14 y"} {:process 41, :type :invoke, :f :append, :key "2", :value "x 41 11 y"} {:process 2, :type :ok, :f :get, :key "5", :value "x 14 5 yx 38 5 yx 39 2 yx 47 11 yx 38 12 yx 9 4 yx 39 5 yx 8 10 yx 14 12 yx 8 12 yx 35 7 yx 6 7 yx 18 10 yx 15 14 yx 6 10 yx 25 4 yx 1 8 yx 37 4 yx 7 3 yx 7 4 yx 4 12 y"} {:process 2, :type :invoke, :f :append, :key "3", :value "x 2 9 y"} {:process 4, :type :ok, :f :append, :key "3", :value "x 4 13 y"} {:process 4, :type :invoke, :f :append, :key "3", :value "x 4 14 y"} {:process 41, :type :ok, :f :append, :key "2", :value "x 41 11 y"} {:process 31, :type :ok, :f :get, :key "8", :value "x 35 8 yx 16 6 yx 3 7 yx 45 21 yx 6 6 yx 16 8 yx 9 6 yx 6 8 yx 34 8 yx 6 12 yx 1 12 yx 4 11 y"} {:process 41, :type :invoke, :f :append, :key "9", :value "x 41 12 y"} {:process 31, :type :invoke, :f :get, :key "2", :value nil} {:process 26, :type :ok, :f :get, :key "3", :value "x 28 16 yx 8 8 yx 31 4 yx 43 3 yx 43 4 yx 35 4 yx 8 13 yx 16 3 yx 18 6 yx 3 8 yx 17 13 yx 18 9 yx 44 14 yx 4 13 y"} {:process 26, :type :invoke, :f :append, :key "4", :value "x 26 9 y"} {:process 2, :type :ok, :f :append, :key "3", :value "x 2 9 y"} {:process 2, :type :invoke, :f :put, :key "5", :value "x 2 10 y"} {:process 4, :type :ok, :f :append, :key "3", :value "x 4 14 y"} {:process 4, :type :invoke, :f :append, :key "4", :value "x 4 15 y"} {:process 14, :type :ok, :f :get, :key "1", :value "x 6 13 yx 31 8 yx 42 12 y"} {:process 14, :type :invoke, :f :append, :key "6", :value "x 14 13 y"} {:process 31, :type :ok, :f :get, :key "2", :value "x 6 5 yx 18 7 yx 18 8 yx 34 6 yx 34 7 yx 29 2 yx 22 9 yx 1 7 yx 1 13 yx 42 7 yx 19 4 yx 7 5 yx 23 6 yx 41 11 y"} {:process 31, :type :invoke, :f :append, :key "6", :value "x 31 10 y"} {:process 4, :type :ok, :f :append, :key "4", :value "x 4 15 y"} {:process 4, :type :invoke, :f :append, :key "6", :value "x 4 16 y"} {:process 2, :type :ok, :f :put, :key "5", :value "x 2 10 y"} {:process 2, :type :invoke, :f :append, :key "4", :value "x 2 11 y"} {:process 26, :type :ok, :f :append, :key "4", :value "x 26 9 y"} {:process 26, :type :invoke, :f :append, :key "4", :value "x 26 10 y"} {:process 26, :type :ok, :f :append, :key "4", :value "x 26 10 y"} {:process 26, :type :invoke, :f :get, :key "0", :value nil} {:process 31, :type :ok, :f :append, :key "6", :value "x 31 10 y"} {:process 31, :type :invoke, :f :get, :key "0", :value nil} {:process 2, :type :ok, :f :append, :key "4", :value "x 2 11 y"} {:process 2, :type :invoke, :f :append, :key "8", :value "x 2 12 y"} {:process 14, :type :ok, :f :append, :key "6", :value "x 14 13 y"} {:process 14, :type :invoke, :f :get, :key "7", :value nil} {:process 14, :type :ok, :f :get, :key "7", :value "x 14 10 yx 38 13 yx 16 7 yx 45 23 yx 46 7 yx 45 24 yx 9 7 yx 6 9 yx 34 9 yx 24 22 yx 25 6 yx 1 11 yx 25 9 yx 42 6 yx 4 10 yx 42 10 yx 2 8 y"} {:process 14, :type :invoke, :f :get, :key "8", :value nil} {:process 26, :type :ok, :f :get, :key "0", :value "x 42 9 yx 37 5 yx 31 6 y"} {:process 26, :type :invoke, :f :get, :key "8", :value nil} {:process 31, :type :ok, :f :get, :key "0", :value "x 42 9 yx 37 5 yx 31 6 y"} {:process 31, :type :invoke, :f :get, :key "9", :value nil} {:process 12, :type :ok, :f :get, :key "7", :value "x 14 10 yx 38 13 yx 16 7 yx 45 23 yx 46 7 yx 45 24 yx 9 7 yx 6 9 yx 34 9 yx 24 22 yx 25 6 yx 1 11 yx 25 9 yx 42 6 yx 4 10 yx 42 10 yx 2 8 y"} {:process 12, :type :invoke, :f :append, :key "6", :value "x 12 2 y"} {:process 14, :type :ok, :f :get, :key "8", :value "x 35 8 yx 16 6 yx 3 7 yx 45 21 yx 6 6 yx 16 8 yx 9 6 yx 6 8 yx 34 8 yx 6 12 yx 1 12 yx 4 11 y"} {:process 14, :type :invoke, :f :get, :key "4", :value nil} {:process 31, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 yx 38 6 yx 9 3 yx 11 4 yx 9 5 yx 8 11 yx 33 4 yx 16 4 yx 38 14 yx 11 7 yx 20 6 yx 1 9 yx 1 10 yx 23 7 yx 41 12 y"} {:process 31, :type :invoke, :f :append, :key "4", :value "x 31 11 y"} {:process 47, :type :ok, :f :get, :key "6", :value "x 40 4 yx 0 8 yx 25 5 yx 25 7 yx 44 15 yx 31 7 yx 31 10 yx 14 13 yx 4 16 y"} {:process 47, :type :invoke, :f :append, :key "5", :value "x 47 16 y"} {:process 31, :type :ok, :f :append, :key "4", :value "x 31 11 y"} {:process 31, :type :invoke, :f :append, :key "9", :value "x 31 12 y"} {:process 14, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 yx 49 7 yx 0 5 yx 44 13 yx 9 8 yx 1 6 yx 6 11 yx 25 8 yx 42 8 yx 39 6 yx 39 7 yx 31 9 yx 42 11 yx 4 15 yx 26 9 yx 26 10 yx 2 11 yx 31 11 y"} {:process 14, :type :invoke, :f :append, :key "6", :value "x 14 14 y"} {:process 47, :type :ok, :f :append, :key "5", :value "x 47 16 y"} {:process 47, :type :invoke, :f :append, :key "9", :value "x 47 17 y"} {:process 14, :type :ok, :f :append, :key "6", :value "x 14 14 y"} {:process 14, :type :invoke, :f :append, :key "3", :value "x 14 15 y"} {:process 33, :type :ok, :f :get, :key "8", :value "x 35 8 yx 16 6 yx 3 7 yx 45 21 yx 6 6 yx 16 8 yx 9 6 yx 6 8 yx 34 8 yx 6 12 yx 1 12 yx 4 11 y"} {:process 33, :type :invoke, :f :append, :key "6", :value "x 33 5 y"} {:process 36, :type :ok, :f :get, :key "8", :value "x 35 8 yx 16 6 yx 3 7 yx 45 21 yx 6 6 yx 16 8 yx 9 6 yx 6 8 yx 34 8 yx 6 12 yx 1 12 yx 4 11 y"} {:process 36, :type :invoke, :f :get, :key "9", :value nil} {:process 33, :type :ok, :f :append, :key "6", :value "x 33 5 y"} {:process 33, :type :invoke, :f :get, :key "8", :value nil} {:process 36, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 yx 38 6 yx 9 3 yx 11 4 yx 9 5 yx 8 11 yx 33 4 yx 16 4 yx 38 14 yx 11 7 yx 20 6 yx 1 9 yx 1 10 yx 23 7 yx 41 12 yx 31 12 yx 47 17 y"} {:process 36, :type :invoke, :f :append, :key "0", :value "x 36 12 y"} {:process 8, :type :ok, :f :append, :key "2", :value "x 8 16 y"} {:process 8, :type :invoke, :f :append, :key "6", :value "x 8 17 y"} {:process 36, :type :ok, :f :append, :key "0", :value "x 36 12 y"} {:process 36, :type :invoke, :f :append, :key "2", :value "x 36 13 y"} {:process 38, :type :ok, :f :append, :key "5", :value "x 38 15 y"} {:process 38, :type :invoke, :f :get, :key "4", :value nil} {:process 36, :type :ok, :f :append, :key "2", :value "x 36 13 y"} {:process 36, :type :invoke, :f :append, :key "3", :value "x 36 14 y"} {:process 36, :type :ok, :f :append, :key "3", :value "x 36 14 y"} {:process 36, :type :invoke, :f :get, :key "5", :value nil} {:process 36, :type :ok, :f :get, :key "5", :value "x 2 10 yx 47 16 yx 38 15 y"} {:process 36, :type :invoke, :f :put, :key "0", :value "x 36 15 y"} {:process 36, :type :ok, :f :put, :key "0", :value "x 36 15 y"} {:process 36, :type :invoke, :f :append, :key "2", :value "x 36 16 y"} {:process 36, :type :ok, :f :append, :key "2", :value "x 36 16 y"} {:process 36, :type :invoke, :f :append, :key "0", :value "x 36 17 y"} {:process 36, :type :ok, :f :append, :key "0", :value "x 36 17 y"} {:process 36, :type :invoke, :f :append, :key "8", :value "x 36 18 y"} {:process 32, :type :ok, :f :append, :key "3", :value "x 32 4 y"} {:process 32, :type :invoke, :f :get, :key "3", :value nil} {:process 36, :type :ok, :f :append, :key "8", :value "x 36 18 y"} {:process 36, :type :invoke, :f :get, :key "7", :value nil} {:process 36, :type :ok, :f :get, :key "7", :value "x 14 10 yx 38 13 yx 16 7 yx 45 23 yx 46 7 yx 45 24 yx 9 7 yx 6 9 yx 34 9 yx 24 22 yx 25 6 yx 1 11 yx 25 9 yx 42 6 yx 4 10 yx 42 10 yx 2 8 y"} {:process 36, :type :invoke, :f :append, :key "5", :value "x 36 19 y"} {:process 17, :type :ok, :f :append, :key "1", :value "x 17 15 y"} {:process 17, :type :invoke, :f :get, :key "1", :value nil} {:process 36, :type :ok, :f :append, :key "5", :value "x 36 19 y"} {:process 36, :type :invoke, :f :append, :key "8", :value "x 36 20 y"} {:process 21, :type :ok, :f :append, :key "2", :value "x 21 12 y"} {:process 21, :type :invoke, :f :get, :key "0", :value nil} {:process 49, :type :ok, :f :append, :key "4", :value "x 49 7 y"} {:process 49, :type :invoke, :f :append, :key "9", :value "x 49 8 y"} {:process 10, :type :ok, :f :append, :key "8", :value "x 10 5 y"} {:process 10, :type :invoke, :f :get, :key "0", :value nil} {:process 17, :type :ok, :f :get, :key "1", :value "x 6 13 yx 31 8 yx 42 12 yx 17 15 y"} {:process 17, :type :invoke, :f :append, :key "9", :value "x 17 16 y"} {:process 21, :type :ok, :f :get, :key "0", :value "x 36 15 yx 36 17 y"} {:process 21, :type :invoke, :f :get, :key "1", :value nil} {:process 10, :type :ok, :f :get, :key "0", :value "x 36 15 yx 36 17 y"} {:process 10, :type :invoke, :f :get, :key "1", :value nil} {:process 49, :type :ok, :f :append, :key "9", :value "x 49 8 y"} {:process 49, :type :invoke, :f :append, :key "5", :value "x 49 9 y"} {:process 28, :type :ok, :f :get, :key "7", :value "x 14 10 yx 38 13 yx 16 7 yx 45 23 yx 46 7 yx 45 24 yx 9 7 yx 6 9 yx 34 9 yx 24 22 yx 25 6 yx 1 11 yx 25 9 yx 42 6 yx 4 10 yx 42 10 yx 2 8 y"} {:process 28, :type :invoke, :f :get, :key "2", :value nil} {:process 46, :type :ok, :f :append, :key "0", :value "x 46 8 y"} {:process 46, :type :invoke, :f :get, :key "9", :value nil} {:process 16, :type :ok, :f :append, :key "3", :value "x 16 11 y"} {:process 16, :type :invoke, :f :append, :key "1", :value "x 16 12 y"} {:process 17, :type :ok, :f :append, :key "9", :value "x 17 16 y"} {:process 17, :type :invoke, :f :append, :key "0", :value "x 17 17 y"} {:process 10, :type :ok, :f :get, :key "1", :value "x 6 13 yx 31 8 yx 42 12 yx 17 15 y"} {:process 10, :type :invoke, :f :append, :key "4", :value "x 10 6 y"} {:process 45, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 yx 49 7 yx 0 5 yx 44 13 yx 9 8 yx 1 6 yx 6 11 yx 25 8 yx 42 8 yx 39 6 yx 39 7 yx 31 9 yx 42 11 yx 4 15 yx 26 9 yx 26 10 yx 2 11 yx 31 11 y"} {:process 18, :type :ok, :f :get, :key "6", :value "x 40 4 yx 0 8 yx 25 5 yx 25 7 yx 44 15 yx 31 7 yx 31 10 yx 14 13 yx 4 16 yx 14 14 yx 33 5 yx 8 17 y"} {:process 8, :type :ok, :f :append, :key "6", :value "x 8 17 y"} {:process 21, :type :ok, :f :get, :key "1", :value "x 6 13 yx 31 8 yx 42 12 yx 17 15 y"} {:process 49, :type :ok, :f :append, :key "5", :value "x 49 9 y"} {:process 23, :type :ok, :f :append, :key "5", :value "x 23 8 y"} {:process 28, :type :ok, :f :get, :key "2", :value "x 6 5 yx 18 7 yx 18 8 yx 34 6 yx 34 7 yx 29 2 yx 22 9 yx 1 7 yx 1 13 yx 42 7 yx 19 4 yx 7 5 yx 23 6 yx 41 11 yx 36 13 yx 36 16 yx 21 12 y"} {:process 9, :type :ok, :f :append, :key "4", :value "x 9 8 y"} {:process 38, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 yx 49 7 yx 0 5 yx 44 13 yx 9 8 yx 1 6 yx 6 11 yx 25 8 yx 42 8 yx 39 6 yx 39 7 yx 31 9 yx 42 11 yx 4 15 yx 26 9 yx 26 10 yx 2 11 yx 31 11 y"} {:process 43, :type :ok, :f :get, :key "3", :value "x 28 16 yx 8 8 yx 31 4 yx 43 3 yx 43 4 yx 35 4 yx 8 13 yx 16 3 yx 18 6 yx 3 8 yx 17 13 yx 18 9 yx 44 14 yx 4 13 yx 2 9 yx 4 14 yx 14 15 yx 36 14 yx 32 4 yx 16 11 y"} {:process 20, :type :ok, :f :append, :key "1", :value "x 20 7 y"} {:process 19, :type :ok, :f :get, :key "0", :value "x 36 15 yx 36 17 y"} {:process 22, :type :ok, :f :get, :key "8", :value "x 35 8 yx 16 6 yx 3 7 yx 45 21 yx 6 6 yx 16 8 yx 9 6 yx 6 8 yx 34 8 yx 6 12 yx 1 12 yx 4 11 yx 36 18 yx 36 20 yx 10 5 y"} {:process 2, :type :ok, :f :append, :key "8", :value "x 2 12 y"} {:process 24, :type :ok, :f :get, :key "3", :value "x 28 16 yx 8 8 yx 31 4 yx 43 3 yx 43 4 yx 35 4 yx 8 13 yx 16 3 yx 18 6 yx 3 8 yx 17 13 yx 18 9 yx 44 14 yx 4 13 yx 2 9 yx 4 14 yx 14 15 yx 36 14 yx 32 4 yx 16 11 y"} {:process 12, :type :ok, :f :append, :key "6", :value "x 12 2 y"} {:process 48, :type :ok, :f :get, :key "0", :value "x 36 15 yx 36 17 y"} {:process 32, :type :ok, :f :get, :key "3", :value "x 28 16 yx 8 8 yx 31 4 yx 43 3 yx 43 4 yx 35 4 yx 8 13 yx 16 3 yx 18 6 yx 3 8 yx 17 13 yx 18 9 yx 44 14 yx 4 13 yx 2 9 yx 4 14 yx 14 15 yx 36 14 yx 32 4 yx 16 11 y"} {:process 36, :type :ok, :f :append, :key "8", :value "x 36 20 y"} {:process 42, :type :ok, :f :append, :key "1", :value "x 42 12 y"} {:process 39, :type :ok, :f :get, :key "5", :value "x 2 10 yx 47 16 yx 38 15 yx 36 19 yx 49 9 y"} {:process 16, :type :ok, :f :append, :key "1", :value "x 16 12 y"} {:process 15, :type :ok, :f :get, :key "1", :value "x 6 13 yx 31 8 yx 42 12 yx 17 15 yx 20 7 yx 16 12 y"} {:process 4, :type :ok, :f :append, :key "6", :value "x 4 16 y"} {:process 13, :type :ok, :f :get, :key "4", :value "x 26 7 yx 47 14 yx 49 7 yx 0 5 yx 44 13 yx 9 8 yx 1 6 yx 6 11 yx 25 8 yx 42 8 yx 39 6 yx 39 7 yx 31 9 yx 42 11 yx 4 15 yx 26 9 yx 26 10 yx 2 11 yx 31 11 yx 0 10 yx 10 6 y"} {:process 40, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 yx 38 6 yx 9 3 yx 11 4 yx 9 5 yx 8 11 yx 33 4 yx 16 4 yx 38 14 yx 11 7 yx 20 6 yx 1 9 yx 1 10 yx 23 7 yx 41 12 yx 31 12 yx 47 17 yx 49 8 yx 17 16 y"} {:process 46, :type :ok, :f :get, :key "9", :value "x 35 1 yx 19 1 yx 40 2 yx 31 0 yx 9 0 yx 41 8 yx 10 0 yx 23 2 yx 26 3 yx 26 6 yx 45 4 yx 26 7 yx 7 9 yx 31 6 yx 26 9 yx 46 6 yx 42 10 yx 48 2 yx 20 6 yx 1 6 yx 14 16 yx 24 6 yx 41 2 yx 45 8 yx 23 1 yx 30 2 yx 21 3 yx 45 9 yx 45 10 yx 21 6 yx 5 1 yx 45 14 yx 22 7 yx 18 1 yx 42 3 yx 16 1 yx 4 6 yx 0 0 yx 41 9 yx 24 10 yx 13 0 yx 24 12 yx 17 9 yx 3 5 yx 17 11 yx 38 1 yx 48 2 yx 38 6 yx 9 3 yx 11 4 yx 9 5 yx 8 11 yx 33 4 yx 16 4 yx 38 14 yx 11 7 yx 20 6 yx 1 9 yx 1 10 yx 23 7 yx 41 12 yx 31 12 yx 47 17 yx 49 8 yx 17 16 y"} {:process 7, :type :ok, :f :append, :key "2", :value "x 7 5 y"} {:process 17, :type :ok, :f :append, :key "0", :value "x 17 17 y"} {:process 27, :type :ok, :f :append, :key "7", :value "x 27 3 y"} {:process 44, :type :ok, :f :append, :key "1", :value "x 44 16 y"} {:process 47, :type :ok, :f :append, :key "9", :value "x 47 17 y"} {:process 37, :type :ok, :f :append, :key "0", :value "x 37 5 y"} {:process 26, :type :ok, :f :get, :key "8", :value "x 35 8 yx 16 6 yx 3 7 yx 45 21 yx 6 6 yx 16 8 yx 9 6 yx 6 8 yx 34 8 yx 6 12 yx 1 12 yx 4 11 yx 36 18 yx 36 20 yx 10 5 yx 2 12 y"} {:process 25, :type :ok, :f :append, :key "5", :value "x 25 11 y"} {:process 34, :type :ok, :f :append, :key "9", :value "x 34 10 y"} {:process 35, :type :ok, :f :get, :key "8", :value "x 35 8 yx 16 6 yx 3 7 yx 45 21 yx 6 6 yx 16 8 yx 9 6 yx 6 8 yx 34 8 yx 6 12 yx 1 12 yx 4 11 yx 36 18 yx 36 20 yx 10 5 yx 2 12 y"} {:process 6, :type :ok, :f :put, :key "1", :value "x 6 13 y"} {:process 30, :type :ok, :f :get, :key "7", :value "x 14 10 yx 38 13 yx 16 7 yx 45 23 yx 46 7 yx 45 24 yx 9 7 yx 6 9 yx 34 9 yx 24 22 yx 25 6 yx 1 11 yx 25 9 yx 42 6 yx 4 10 yx 42 10 yx 2 8 yx 27 3 y"} {:process 41, :type :ok, :f :append, :key "9", :value "x 41 12 y"} {:process 31, :type :ok, :f :append, :key "9", :value "x 31 12 y"} {:process 1, :type :ok, :f :append, :key "2", :value "x 1 13 y"} {:process 0, :type :ok, :f :append, :key "4", :value "x 0 10 y"} {:process 29, :type :ok, :f :append, :key "2", :value "x 29 2 y"} {:process 3, :type :ok, :f :get, :key "8", :value "x 35 8 yx 16 6 yx 3 7 yx 45 21 yx 6 6 yx 16 8 yx 9 6 yx 6 8 yx 34 8 yx 6 12 yx 1 12 yx 4 11 yx 36 18 yx 36 20 yx 10 5 yx 2 12 y"} {:process 10, :type :ok, :f :append, :key "4", :value "x 10 6 y"} {:process 14, :type :ok, :f :append, :key "3", :value "x 14 15 y"} {:process 11, :type :ok, :f :get, :key "2", :value "x 6 5 yx 18 7 yx 18 8 yx 34 6 yx 34 7 yx 29 2 yx 22 9 yx 1 7 yx 1 13 yx 42 7 yx 19 4 yx 7 5 yx 23 6 yx 41 11 yx 36 13 yx 36 16 yx 21 12 y"} {:process 33, :type :ok, :f :get, :key "8", :value "x 35 8 yx 16 6 yx 3 7 yx 45 21 yx 6 6 yx 16 8 yx 9 6 yx 6 8 yx 34 8 yx 6 12 yx 1 12 yx 4 11 yx 36 18 yx 36 20 yx 10 5 yx 2 12 y"} {:process 5, :type :ok, :f :get, :key "6", :value "x 40 4 yx 0 8 yx 25 5 yx 25 7 yx 44 15 yx 31 7 yx 31 10 yx 14 13 yx 4 16 yx 14 14 yx 33 5 yx 8 17 yx 12 2 y"} ================================================ FILE: courses/dss/percolator/Cargo.toml ================================================ [package] name = "percolator" version = "0.1.0" authors = ["Ryan Leung "] edition = "2018" build = "build.rs" publish = false [dependencies] async-trait = "0.1" futures = "0.3" futures-timer = "3.0" log = "0.4" prost = "0.6" prost-derive = "0.6" labrpc = { path = "../labrpc" } labcodec = { path = "../labcodec" } [build-dependencies] prost-build = "0.6" [dev-dependencies] env_logger = "0.7" ================================================ FILE: courses/dss/percolator/README.md ================================================ # The Percolator lab ## What is Percolator Percolator is a system built by Google for incremental processing on a very large data set. Percolator also provides a distributed transaction protocol with ACID snapshot-isolation semantics. You can find more details in the paper: [Large-scale Incremental Processing Using Distributed Transactions and Notifications](https://storage.googleapis.com/pub-tools-public-publication-data/pdf/36726.pdf). ## Lab prerequisites To start this lab, there are some prerequisites you need to: 1. be familiar with Rust (You can also learn something from our Rust training course) 2. know about how protobuf works 3. have basic knowledge of how RPC works 4. have basic knowledge of what is the distributed transaction ## Concepts of the lab ### Server There are two kinds of servers which provide different services in this lab: the TSO server and the storage server. #### TSO server Percolator relies on a service named *timestamp oracle*. The TSO server implemented by `TimestampOracle` can produce timestamps in a strictly increasing order. All transactions need to get the unique timestamp to indicate the execution order. #### Storage server Percolator is built upon the Bigtable, which presents a multi-dimensional sorted map to users. In this lab, the storage server implemented by `MemoryStorage`, which consists of three columns, is used to simulate the Bigtable. These columns which implemented by `BTreeMap` are similar to the column in the Bigtable. In particular, the `MemoryStorage` has three columns: `Write`, `Data`, `Lock` to keep consistent with the Bigtable. Besides, the storage also needs to provide the basic operations like `read`, `write` and `erase` to manipulate the data stored in it. ### Client The client will `begin` a transaction which contains a set of operations, like `get` and `set`, and call `commit` to commit a transaction. Also, the client will call `get_timestamp` to obtain a timestamp. More implementation details can be found in the paper. ## Writing your own implementation There are some comments leaving in this project such as "Your definitions here" or "Your code here". You need to write the code by yourself according to the paper. There are not many strict restrictions, and thus you can define as many variables in both *struct* and *proto* as required to implement the functionality. ## Testing your work You can directly run the following command in the current directory: ```sh make test_percolator ``` ================================================ FILE: courses/dss/percolator/build.rs ================================================ fn main() { prost_build::compile_protos(&["proto/msg.proto"], &["proto"]).unwrap(); println!("cargo:rerun-if-changed=proto"); } ================================================ FILE: courses/dss/percolator/proto/msg.proto ================================================ // Protocol buffers are a flexible, efficient, automated mechanism for serializing structured data. // You can define how you want your data to be structured. // Details can be found in https://developers.google.com/protocol-buffers/docs/proto3. // Once you have defined the message, the `build.rs` will generate the corresponding data structure in `OUT_DIR`. // You can use the structure by importing the `msg` module. // Example: // use crate::msg::CommitRequest; syntax = "proto3"; package msg; message TimestampRequest {} message TimestampResponse {} message GetRequest {} message GetResponse {} message PrewriteRequest {} message PrewriteResponse {} message CommitRequest { bool is_primary = 1; } message CommitResponse {} ================================================ FILE: courses/dss/percolator/src/client.rs ================================================ use labrpc::*; use crate::service::{TSOClient, TransactionClient}; // BACKOFF_TIME_MS is the wait time before retrying to send the request. // It should be exponential growth. e.g. //| retry time | backoff time | //|--------------|----------------| //| 1 | 100 | //| 2 | 200 | //| 3 | 400 | const BACKOFF_TIME_MS: u64 = 100; // RETRY_TIMES is the maximum number of times a client attempts to send a request. const RETRY_TIMES: usize = 3; /// Client mainly has two purposes: /// One is getting a monotonically increasing timestamp from TSO (Timestamp Oracle). /// The other is do the transaction logic. #[derive(Clone)] pub struct Client { // Your definitions here. } impl Client { /// Creates a new Client. pub fn new(tso_client: TSOClient, txn_client: TransactionClient) -> Client { // Your code here. Client {} } /// Gets a timestamp from a TSO. pub fn get_timestamp(&self) -> Result { // Your code here. unimplemented!() } /// Begins a new transaction. pub fn begin(&mut self) { // Your code here. unimplemented!() } /// Gets the value for a given key. pub fn get(&self, key: Vec) -> Result> { // Your code here. unimplemented!() } /// Sets keys in a buffer until commit time. pub fn set(&mut self, key: Vec, value: Vec) { // Your code here. unimplemented!() } /// Commits a transaction. pub fn commit(&self) -> Result { // Your code here. unimplemented!() } } ================================================ FILE: courses/dss/percolator/src/lib.rs ================================================ #[allow(unused_imports)] #[macro_use] extern crate log; // After you finish the implementation, `#[allow(unused)]` should be removed. #[allow(dead_code, unused)] mod client; #[allow(unused)] mod server; mod service; #[cfg(test)] mod tests; // This is related to protobuf as described in `msg.proto`. mod msg { include!(concat!(env!("OUT_DIR"), "/msg.rs")); } ================================================ FILE: courses/dss/percolator/src/server.rs ================================================ use std::collections::BTreeMap; use std::sync::{Arc, Mutex}; use std::time::Duration; use crate::msg::*; use crate::service::*; use crate::*; // TTL is used for a lock key. // If the key's lifetime exceeds this value, it should be cleaned up. // Otherwise, the operation should back off. const TTL: u64 = Duration::from_millis(100).as_nanos() as u64; #[derive(Clone, Default)] pub struct TimestampOracle { // You definitions here if needed. } #[async_trait::async_trait] impl timestamp::Service for TimestampOracle { // example get_timestamp RPC handler. async fn get_timestamp(&self, _: TimestampRequest) -> labrpc::Result { // Your code here. unimplemented!() } } // Key is a tuple (raw key, timestamp). pub type Key = (Vec, u64); #[derive(Clone, PartialEq)] pub enum Value { Timestamp(u64), Vector(Vec), } #[derive(Debug, Clone)] pub struct Write(Vec, Vec); pub enum Column { Write, Data, Lock, } // KvTable is used to simulate Google's Bigtable. // It provides three columns: Write, Data, and Lock. #[derive(Clone, Default)] pub struct KvTable { write: BTreeMap, data: BTreeMap, lock: BTreeMap, } impl KvTable { // Reads the latest key-value record from a specified column // in MemoryStorage with a given key and a timestamp range. #[inline] fn read( &self, key: Vec, column: Column, ts_start_inclusive: Option, ts_end_inclusive: Option, ) -> Option<(&Key, &Value)> { // Your code here. unimplemented!() } // Writes a record to a specified column in MemoryStorage. #[inline] fn write(&mut self, key: Vec, column: Column, ts: u64, value: Value) { // Your code here. unimplemented!() } #[inline] // Erases a record from a specified column in MemoryStorage. fn erase(&mut self, key: Vec, column: Column, commit_ts: u64) { // Your code here. unimplemented!() } } // MemoryStorage is used to wrap a KvTable. // You may need to get a snapshot from it. #[derive(Clone, Default)] pub struct MemoryStorage { data: Arc>, } #[async_trait::async_trait] impl transaction::Service for MemoryStorage { // example get RPC handler. async fn get(&self, req: GetRequest) -> labrpc::Result { // Your code here. unimplemented!() } // example prewrite RPC handler. async fn prewrite(&self, req: PrewriteRequest) -> labrpc::Result { // Your code here. unimplemented!() } // example commit RPC handler. async fn commit(&self, req: CommitRequest) -> labrpc::Result { // Your code here. unimplemented!() } } impl MemoryStorage { fn back_off_maybe_clean_up_lock(&self, start_ts: u64, key: Vec) { // Your code here. unimplemented!() } } ================================================ FILE: courses/dss/percolator/src/service.rs ================================================ use crate::msg::{ CommitRequest, CommitResponse, GetRequest, GetResponse, PrewriteRequest, PrewriteResponse, TimestampRequest, TimestampResponse, }; labrpc::service! { service timestamp { rpc get_timestamp(TimestampRequest) returns (TimestampResponse); } } pub use timestamp::{add_service as add_tso_service, Client as TSOClient, Service}; labrpc::service! { service transaction { rpc get(GetRequest) returns (GetResponse); rpc prewrite(PrewriteRequest) returns (PrewriteResponse); rpc commit(CommitRequest) returns (CommitResponse); } } pub use transaction::{add_service as add_transaction_service, Client as TransactionClient}; ================================================ FILE: courses/dss/percolator/src/tests.rs ================================================ use std::sync::{ atomic::{AtomicBool, Ordering}, Arc, }; use std::thread; use std::time::Duration; use labrpc::*; use prost::Message; use crate::client::Client; use crate::server::{MemoryStorage, TimestampOracle}; use crate::service::{add_transaction_service, add_tso_service, TSOClient, TransactionClient}; struct CommitHooks { drop_req: AtomicBool, drop_resp: AtomicBool, fail_primary: AtomicBool, } impl RpcHooks for CommitHooks { fn before_dispatch(&self, fq_name: &str, req: &[u8]) -> Result<()> { if self.drop_req.load(Ordering::Relaxed) && fq_name == "transaction.commit" { let m = crate::msg::CommitRequest::decode(req).unwrap(); if m.is_primary && !self.fail_primary.load(Ordering::Relaxed) { return Ok(()); } return Err(Error::Other("reqhook".to_owned())); } Ok(()) } fn after_dispatch(&self, fq_name: &str, resp: Result>) -> Result> { if self.drop_resp.load(Ordering::Relaxed) && fq_name == "transaction.commit" { return Err(Error::Other("resphook".to_owned())); } resp } } fn init_logger() { use std::sync::Once; static LOGGER_INIT: Once = Once::new(); LOGGER_INIT.call_once(env_logger::init); } fn init(num_clinet: usize) -> (Network, Vec, Arc) { init_logger(); let mut clients = vec![]; let rn = Network::new(); let tso_server_name = "tso_server"; let mut tso_server_builder = ServerBuilder::new(tso_server_name.to_owned()); let server_name = "server"; let mut server_builder = ServerBuilder::new(server_name.to_owned()); let tso: TimestampOracle = Default::default(); add_tso_service(tso, &mut tso_server_builder).unwrap(); let store: MemoryStorage = Default::default(); add_transaction_service(store, &mut server_builder).unwrap(); let tso_server = tso_server_builder.build(); let server = server_builder.build(); rn.add_server(tso_server); rn.add_server(server); let hook = Arc::new(CommitHooks { drop_req: AtomicBool::new(false), drop_resp: AtomicBool::new(false), fail_primary: AtomicBool::new(false), }); for i in 0..num_clinet { let txn_name_string = format!("txn{}", i); let txn_name = txn_name_string.as_str(); let cli = rn.create_client(txn_name.to_owned()); cli.set_hooks(hook.clone()); let txn_client = TransactionClient::new(cli); rn.enable(txn_name, true); rn.connect(txn_name, server_name); let tso_name_string = format!("tso{}", i); let tso_name = tso_name_string.as_str(); let cli = rn.create_client(tso_name.to_owned()); let tso_client = TSOClient::new(cli); rn.enable(tso_name, true); rn.connect(tso_name, tso_server_name); clients.push(crate::client::Client::new(tso_client, txn_client)); } (rn, clients, hook) } #[test] fn test_get_timestamp_under_unreliable_network() { let (rn, clients, _) = init(3); let mut children = vec![]; for (i, _) in clients.iter().enumerate() { let client = clients[i].to_owned(); let tso_name_string = format!("tso{}", i); rn.enable(tso_name_string.as_str(), false); children.push(thread::spawn(move || { let res = client.get_timestamp(); if i == 2 { assert_eq!(res, Err(Error::Timeout)); } else { assert!(res.is_ok()); } })); } thread::sleep(Duration::from_millis(100)); rn.enable("tso0", true); thread::sleep(Duration::from_millis(200)); rn.enable("tso1", true); thread::sleep(Duration::from_millis(400)); rn.enable("tso2", true); for child in children { child.join().unwrap(); } } #[test] // https://github.com/ept/hermitage/blob/master/sqlserver.md#predicate-many-preceders-pmp fn test_predicate_many_preceders_read_predicates() { let (_, clients, _) = init(3); let mut client0 = clients[0].to_owned(); client0.begin(); client0.set(b"1".to_vec(), b"10".to_vec()); client0.set(b"2".to_vec(), b"20".to_vec()); assert_eq!(client0.commit(), Ok(true)); let mut client1 = clients[1].to_owned(); client1.begin(); assert_eq!(client1.get(b"3".to_vec()), Ok(Vec::new())); let mut client2 = clients[2].to_owned(); client2.begin(); client2.set(b"3".to_vec(), b"30".to_vec()); assert_eq!(client2.commit(), Ok(true)); assert_eq!(client1.get(b"3".to_vec()), Ok(Vec::new())); } #[test] // https://github.com/ept/hermitage/blob/master/sqlserver.md#predicate-many-preceders-pmp fn test_predicate_many_preceders_write_predicates() { let (_, clients, _) = init(3); let mut client0 = clients[0].to_owned(); client0.begin(); client0.set(b"1".to_vec(), b"10".to_vec()); client0.set(b"2".to_vec(), b"20".to_vec()); assert_eq!(client0.commit(), Ok(true)); let mut client1 = clients[1].to_owned(); client1.begin(); let mut client2 = clients[2].to_owned(); client2.begin(); client1.set(b"1".to_vec(), b"20".to_vec()); client1.set(b"2".to_vec(), b"30".to_vec()); assert_eq!(client1.get(b"2".to_vec()), Ok(b"20".to_vec())); client2.set(b"2".to_vec(), b"40".to_vec()); assert_eq!(client1.commit(), Ok(true)); assert_eq!(client2.commit(), Ok(false)); } #[test] // https://github.com/ept/hermitage/blob/master/sqlserver.md#lost-update-p4 fn test_lost_update() { let (_, clients, _) = init(3); let mut client0 = clients[0].to_owned(); client0.begin(); client0.set(b"1".to_vec(), b"10".to_vec()); client0.set(b"2".to_vec(), b"20".to_vec()); assert_eq!(client0.commit(), Ok(true)); let mut client1 = clients[1].to_owned(); client1.begin(); let mut client2 = clients[2].to_owned(); client2.begin(); assert_eq!(client1.get(b"1".to_vec()), Ok(b"10".to_vec())); assert_eq!(client2.get(b"1".to_vec()), Ok(b"10".to_vec())); client1.set(b"1".to_vec(), b"11".to_vec()); client2.set(b"1".to_vec(), b"11".to_vec()); assert_eq!(client1.commit(), Ok(true)); assert_eq!(client2.commit(), Ok(false)); } #[test] // https://github.com/ept/hermitage/blob/master/sqlserver.md#read-skew-g-single fn test_read_skew_read_only() { let (_, clients, _) = init(3); let mut client0 = clients[0].to_owned(); client0.begin(); client0.set(b"1".to_vec(), b"10".to_vec()); client0.set(b"2".to_vec(), b"20".to_vec()); assert_eq!(client0.commit(), Ok(true)); let mut client1 = clients[1].to_owned(); client1.begin(); let mut client2 = clients[2].to_owned(); client2.begin(); assert_eq!(client1.get(b"1".to_vec()), Ok(b"10".to_vec())); assert_eq!(client2.get(b"1".to_vec()), Ok(b"10".to_vec())); assert_eq!(client2.get(b"2".to_vec()), Ok(b"20".to_vec())); client2.set(b"1".to_vec(), b"12".to_vec()); client2.set(b"2".to_vec(), b"18".to_vec()); assert_eq!(client2.commit(), Ok(true)); assert_eq!(client1.get(b"2".to_vec()), Ok(b"20".to_vec())); } #[test] // https://github.com/ept/hermitage/blob/master/sqlserver.md#read-skew-g-single fn test_read_skew_predicate_dependencies() { let (_, clients, _) = init(3); let mut client0 = clients[0].to_owned(); client0.begin(); client0.set(b"1".to_vec(), b"10".to_vec()); client0.set(b"2".to_vec(), b"20".to_vec()); assert_eq!(client0.commit(), Ok(true)); let mut client1 = clients[1].to_owned(); client1.begin(); let mut client2 = clients[2].to_owned(); client2.begin(); assert_eq!(client1.get(b"1".to_vec()), Ok(b"10".to_vec())); assert_eq!(client1.get(b"2".to_vec()), Ok(b"20".to_vec())); client2.set(b"3".to_vec(), b"30".to_vec()); assert_eq!(client2.commit(), Ok(true)); assert_eq!(client1.get(b"3".to_vec()), Ok(Vec::new())); } #[test] // https://github.com/ept/hermitage/blob/master/sqlserver.md#read-skew-g-single fn test_read_skew_write_predicate() { let (_, clients, _) = init(3); let mut client0 = clients[0].to_owned(); client0.begin(); client0.set(b"1".to_vec(), b"10".to_vec()); client0.set(b"2".to_vec(), b"20".to_vec()); assert_eq!(client0.commit(), Ok(true)); let mut client1 = clients[1].to_owned(); client1.begin(); let mut client2 = clients[2].to_owned(); client2.begin(); assert_eq!(client1.get(b"1".to_vec()), Ok(b"10".to_vec())); assert_eq!(client2.get(b"1".to_vec()), Ok(b"10".to_vec())); assert_eq!(client2.get(b"2".to_vec()), Ok(b"20".to_vec())); client2.set(b"1".to_vec(), b"12".to_vec()); client2.set(b"2".to_vec(), b"18".to_vec()); assert_eq!(client2.commit(), Ok(true)); client1.set(b"2".to_vec(), b"30".to_vec()); assert_eq!(client1.commit(), Ok(false)); } #[test] // https://github.com/ept/hermitage/blob/master/sqlserver.md#write-skew-g2-item fn test_write_skew() { let (_, clients, _) = init(3); let mut client0 = clients[0].to_owned(); client0.begin(); client0.set(b"1".to_vec(), b"10".to_vec()); client0.set(b"2".to_vec(), b"20".to_vec()); assert_eq!(client0.commit(), Ok(true)); let mut client1 = clients[1].to_owned(); client1.begin(); let mut client2 = clients[2].to_owned(); client2.begin(); assert_eq!(client1.get(b"1".to_vec()), Ok(b"10".to_vec())); assert_eq!(client1.get(b"2".to_vec()), Ok(b"20".to_vec())); assert_eq!(client2.get(b"1".to_vec()), Ok(b"10".to_vec())); assert_eq!(client2.get(b"2".to_vec()), Ok(b"20".to_vec())); client1.set(b"1".to_vec(), b"11".to_vec()); client2.set(b"2".to_vec(), b"21".to_vec()); assert_eq!(client1.commit(), Ok(true)); assert_eq!(client2.commit(), Ok(true)); } #[test] // https://github.com/ept/hermitage/blob/master/sqlserver.md#anti-dependency-cycles-g2 fn test_anti_dependency_cycles() { let (_, clients, _) = init(4); let mut client0 = clients[0].to_owned(); client0.begin(); client0.set(b"1".to_vec(), b"10".to_vec()); client0.set(b"2".to_vec(), b"20".to_vec()); assert_eq!(client0.commit(), Ok(true)); let mut client1 = clients[1].to_owned(); client1.begin(); let mut client2 = clients[2].to_owned(); client2.begin(); client1.set(b"3".to_vec(), b"30".to_vec()); client2.set(b"4".to_vec(), b"42".to_vec()); assert_eq!(client1.commit(), Ok(true)); assert_eq!(client2.commit(), Ok(true)); let mut client3 = clients[3].to_owned(); client3.begin(); assert_eq!(client3.get(b"3".to_vec()), Ok(b"30".to_vec())); assert_eq!(client3.get(b"4".to_vec()), Ok(b"42".to_vec())); } #[test] fn test_commit_primary_drop_secondary_requests() { let (_, clients, hook) = init(2); let mut client0 = clients[0].to_owned(); client0.begin(); client0.set(b"3".to_vec(), b"30".to_vec()); client0.set(b"4".to_vec(), b"40".to_vec()); client0.set(b"5".to_vec(), b"50".to_vec()); hook.drop_req.store(true, Ordering::Relaxed); assert_eq!(client0.commit(), Ok(true)); let mut client1 = clients[1].to_owned(); client1.begin(); assert_eq!(client1.get(b"3".to_vec()).unwrap(), b"30"); assert_eq!(client1.get(b"4".to_vec()).unwrap(), b"40"); assert_eq!(client1.get(b"5".to_vec()).unwrap(), b"50"); } #[test] fn test_commit_primary_success() { let (_, clients, hook) = init(2); let mut client0 = clients[0].to_owned(); client0.begin(); client0.set(b"3".to_vec(), b"30".to_vec()); client0.set(b"4".to_vec(), b"40".to_vec()); client0.set(b"5".to_vec(), b"50".to_vec()); hook.drop_req.store(true, Ordering::Relaxed); assert_eq!(client0.commit(), Ok(true)); let mut client1 = clients[1].to_owned(); client1.begin(); assert_eq!(client1.get(b"3".to_vec()).unwrap(), b"30"); assert_eq!(client1.get(b"4".to_vec()).unwrap(), b"40"); assert_eq!(client1.get(b"5".to_vec()).unwrap(), b"50"); } #[test] fn test_commit_primary_success_without_response() { let (_, clients, hook) = init(2); let mut client0 = clients[0].to_owned(); client0.begin(); client0.set(b"3".to_vec(), b"30".to_vec()); client0.set(b"4".to_vec(), b"40".to_vec()); client0.set(b"5".to_vec(), b"50".to_vec()); hook.drop_resp.store(true, Ordering::Relaxed); assert_eq!(client0.commit(), Err(Error::Other("resphook".to_owned()))); let mut client1 = clients[1].to_owned(); client1.begin(); assert_eq!(client1.get(b"3".to_vec()).unwrap(), b"30"); assert_eq!(client1.get(b"4".to_vec()).unwrap(), b"40"); assert_eq!(client1.get(b"5".to_vec()).unwrap(), b"50"); } #[test] fn test_commit_primary_fail() { let (_, clients, hook) = init(2); let mut client0 = clients[0].to_owned(); client0.begin(); client0.set(b"3".to_vec(), b"30".to_vec()); client0.set(b"4".to_vec(), b"40".to_vec()); client0.set(b"5".to_vec(), b"50".to_vec()); hook.drop_req.store(true, Ordering::Relaxed); hook.fail_primary.store(true, Ordering::Relaxed); assert_eq!(client0.commit(), Ok(false)); let mut client1 = clients[1].to_owned(); client1.begin(); assert_eq!(client1.get(b"3".to_vec()), Ok(Vec::new())); assert_eq!(client1.get(b"4".to_vec()), Ok(Vec::new())); assert_eq!(client1.get(b"5".to_vec()), Ok(Vec::new())); } ================================================ FILE: courses/dss/raft/Cargo.toml ================================================ [package] name = "raft" version = "0.1.0" authors = [ "Neil Shen ", "ShuNing ", "Connor ", "庄天翼 ", "MIT 6.824 <6824-staff@lists.csail.mit.edu>" ] edition = "2018" publish = false [dependencies] async-trait = "0.1" futures = "0.3" futures-timer = "3.0" log = "0.4" prost = "0.6" prost-derive = "0.6" rand = "0.7" labcodec = { path = "../labcodec" } labrpc = { path = "../labrpc" } linearizability = { path = "../linearizability"} [dev-dependencies] env_logger = "0.7" [build-dependencies] prost-build = "0.6" ================================================ FILE: courses/dss/raft/README.md ================================================ # The Raft lab This is a series of labs on a key/value storage system built with the Raft consensus algorithm. These labs are derived from the [lab2:raft][6824lab2] and [lab3:kvraft][6824lab3] from the famous [MIT 6.824][6824] course but rewritten in Rust. The following text material is also very influenced by the text material there. [6824lab2]:http://nil.csail.mit.edu/6.824/2018/labs/lab-raft.html [6824lab3]:http://nil.csail.mit.edu/6.824/2018/labs/lab-kvraft.html [6824]:http://nil.csail.mit.edu/6.824/2018/index.html In these labs you will first implement the raft consensus algorithm in the lab2:raft, and then build a key/value service in the lab3:kvraft. Raft is a consensus algorithm that is designed to be easy to understand.You can read material about the Raft itself at [the Raft site][raftsite], including [the extended Raft paper][raftpaper], an interactive visualization of the Raft, and other resource. Those material should be helpful for you to complete this lab. [raftsite]:https://raft.github.io/ ## Getting started First, please clone this repository with `git` to get the source code of the labs. Then, make sure you have `rustup` installed. Also, to make things simpler you should have `make` installed. Now you can run `make test_others` to check that things are going right. You should see all tests passed. (If you are a Windows user, you may have to figure out how to use `make` on Windows, or type the commands from the makefile in the console manually, or just use the Windows Subsystem for Linux) ## The lab2: Raft In this lab you will implement the Raft consensus algorithm. This lab has 3 parts named with 2A, 2B and 2C. To run all the test in this lab, run `make test_2`. Please run the tests multiple times to mak sure your are not passing the tests just by luck. To run just a single test, run `make cargo_test_`. ### The code structure All your codes in this lab should be in the `src/proto/mod.rs`, `src/proto/raft.proto` and `src/raft/mod.rs`. The `src/raft/mod.rs` file should contains your main implementation of Raft. The tester (and your key/value server in lab3) will call methods in this file to use your Raft module. A service calls `Raft::new` to create a Raft peer, and then calls `Node::new` to start the Raft peer. The `Node::get_state`, `Node::is_leader` and `Node::term` will be called to get the current term of the node and whether it thinks it is leader. The `Node::start` will be called when the server need to append the command into the log. `Node::start` should returns immediately without waiting for the log appends to complete. A channel (`apply_ch`) is passed into `Raft::new` and you should send a `ApplyMsg` to the channel for each newly committed log entry. Your implements should use the provided `labrpc` crate to exchange RPCs. The `labrpc` use channels to simulate sockets internally. This makes it easy to test your code under challenging network conditions. Your definition of the RPCs should in `src/proto/mod.rs` and you should implement the RPC server in `impl RaftService for Node`. A set of RPC clients (`peers`) is pass into `Raft::new` for you to send RPCs to other nodes. ### Part 2A In this part you should implement the leader election and heartbeats (`AppendEntries` RPCs without log entries). You should make a single leader to be elected, make leader to remain leader when there are no failures, and have a new leader when old leader fails or packets to/from old leader is lost. To run all the test in this lab, run `make test_2a`. Here are some hints on this part: - Add any state you need to the `Raft` struct. - The `request_vote` RPC is already defined, you just need to fill the `RequestVoteArgs` and `RequestVoteReply` struct. The lab use `labcodec` crate to encode and decode messages in RPC, which internally use the `prost` external crate. See the [prost document][prost] to know how to define structs that is used as messages with `#[Derive(Message)]` and `#[prost(...)]`. - You need to define the `append_entries` RPC by yourself. `labrpc` use a `labrpc::service!` macro to define RPC service and generate server and client traits from your definition. There is an example in `labrpc/examples/echo.rs` which may help you to define new RPCs. - This lab use things from the `futures` external crate heavily like the channels and the `Future` trait. Read things about futures [here][futures]. - You need to make your code take actions periodically or after delays in time. You can use lots of threads and call `std::thread::sleep` ([doc][sleep]), but you can also use the `futures_timer::Delay` and other utilities from the `futures-timer` external crate ([doc][futures-timer]). - Don't forget that you need to make sure that the election timeouts in different peers don't always fire at the same time, or else all peers will vote only for themselves and no one will become the leader. You can generate random numbers using the `rand` external crate ([doc][rand]). - The tester limits the frequency of RPC calls to 10 times per second for each pair of sender and receiver. Please do not just send RPCs repeatedly without wait for a timeout. - The tester requires your Raft to elect a new leader within five seconds of the failure of the old leader (if a majority of peers can still communicate). However, leader election may require multiple rounds in case of a split vote (which can happen if packets are lost or if candidates unluckily choose the same random backoff times). You must pick election timeouts (and thus heartbeat intervals) that are short enough that it's very likely that an election will complete in less than five seconds even if it requires multiple rounds. - But also, since the tester limits the frequency of RPC calls, your election timeout should not be too small, and larger than the 150~300 milliseconds in the paper's Section 5.2. Choose the values wisely. - In Rust we lock data instead of code. Think carefully about what data should be in the same lock. - The Figure 2 in the [Raft paper][raftpaper] is useful when you are in trouble passing the test. - It's useful to debug by printing log messages. We use the external `log` crate ([doc][log]) to print logs in different levels. you can configure the log level and scope by set LOG_LEVEL environment variable like `LOG_LEVEL=labs6824=debug make test_2a`. This feature is provided by the `env_logger` external crate ([doc][env_logger]), read it's documentation for syntax of the log level. Also, you can collect the output in a file by redirecting the output to a file like `make test_2a 2>test.log` [prost]:https://github.com/danburkert/prost [futures]:https://docs.rs/futures/0.3/futures/index.html [sleep]:https://doc.rust-lang.org/std/thread/fn.sleep.html [futures-timer]:https://docs.rs/futures-timer/3.0/futures_timer/index.html [rand]:https://docs.rs/rand/0.7/rand/index.html [log]:https://docs.rs/log/0.4/log/ [env_logger]:https://docs.rs/env_logger/0.7/env_logger/ ### Part 2B In this part you should implement the log replication. You should implement the `Node::Start` method, complete the rest fields in the `append_entries` RPC and send them, and advance `commit_index` at leader. To run all the test in this lab, run `make test_2b`. You can try to pass the `test_basic_agree_2b` test first. Here are some hints on this part: - Don't forget election restriction, see section 5.4.1 in the [Raft paper][raftpaper]. - Every server commit new entries independently by write to `apply_ch` in the correct order. `apply_ch` is a `UnboundedSender` which will buffering the messages until out of memory, so it is not that easy to create deadlocks as the original go version. - Give yourself enough time to rewrite your implementation because only after writing a first implementation will you realize how to organize your code cleanly. - The `test_count_2b` requires your number of RPCs to be not too much when there is no failure. So you should optimize the number of RPCs to the minimum. - You may need to write code that waits for certain events to occur. In that case you can just use channels and wait on it. ### Part 2C In this part you should implement persistence by first adding code that saves and restores persistent state to `Persister`, like in `Raft::persist` and `Raft::restore` using `labcodec`. You also need to determine what and when to persist, and call `Raft::restore` in `Raft::new`. To run all the test in this lab, run `make test_2c`. You can try to pass the `test_persist1_2c` test first. Here are some hints on this part: - The usage of `labcodec` is covered in the hints of part 2A. - This part also introduce various challenging test that involving servers failing and the network losing RPC requests or replies. Check your implementation carefully to find bugs that only present in this situation. - In order to pass some of the challenging tests towards the end, such as those marked "unreliable", you will need to implement the optimization to allow a follower to back up the leader's nextIndex by more than one entry at a time. See the description in the [Raft paper][raftpaper] starting at the bottom of page 7 and top of page 8 (marked by a gray line). However, the paper do not have many details on this. You will need to fill in the gaps, perhaps with the help of [this 6.824 Raft lectures][optimize-hint]. [optimize-hint]:http://nil.csail.mit.edu/6.824/2018/notes/l-raft2.txt ## The lab3: KvRaft In this lab you will build a fault-tolerant key-value storage service using the Raft module in lab 2. This lab has 2 parts named with 3A and 3B. To run all the test in this lab, run `make test_3`. Please run the tests multiple times to mak sure your are not passing the tests just by luck. To run just a single test, run `make cargo_test_`. ### The code structure All your codes in this lab should be in the `src/proto/mod.rs`, `src/proto/kvraft.proto`, `src/kvraft/server.rs` and `src/kvraft/client.rs`. The file name explains what they are. Also, you need to modify the files you touched in lab2:raft. ### Part 3A In this part you should first implement a solution that works when there are no dropped messages, and no failed servers. Your service must ensure that `get(...)` and `put_append(...)` are [linearizable][linearizable]. [linearizable]:https://en.wikipedia.org/wiki/Linearizability That means, completed application calls to the methods on the `Clerk` struct in `src/kvraft/client.rs` must appear to all clients to have affected the service in the same linear order, even in there are failures and leader changes. A `Clerk::Get` that starts after a completed `Clerk::Put` or `Clerk::Append` should see the value written by the most recent `Clerk::Put` or `Clerk::Append` in the linear order. Completed calls should have exactly-once semantics. A reasonable plan of implementation should be: - Client send RPC request in the `src/kvraft/client.rs` - Enter the operation from client into the Raft log by `raft::Node::start` in the RPC handler of `KvServer` - Execute the operation when the raft log committed, and then reply to RPC After implement that you should pass the basic one client test, run `make cargo_test_basic_3a` to check it. Here are some hints on this part: - You should receive commit message from Raft by `apply_ch` at the same time you receives RPC. - If a leader has called `Raft::start` for a Clerk's RPC, but loses its leadership before the request is committed to the log, you should make the client to re-send the RPC request to other servers until it finds the new leader. You can detect this by check things received from `apply_ch`. - The `Clerk` client should remember who is the last leader, and try the last leader first. This will avoid wasting time searching for the leader on every RPC. - The server should not complete a `get` RPC if it is not part of a majority and do not has up-to-date data. You can just put the get operation into the log, or implement the optimization for read-only operations that is described in Section 8 in the [Raft paper][raftpaper]. - Think how to use lock at the beginning. Then, you should deal with duplicate client requests, including situations where the client sends a request to a server leader in one term, times out waiting for a reply, and re-sends the request to a new leader in another term. The request should always execute just once. After this you should pass all tests in this part. To run all the test in this lab, run `make test_3a`. Here are some hints on this part: - You will need to uniquely identify client operations to ensure that the key/ value service executes each one just once. - Your scheme for duplicate detection should free server memory quickly, like using a hashtable for and only for uncommitted logs. ### Part 3B In your current implementation, a rebooting server replays the complete Raft log in order to restore its state. However, it's not practical for a long-running server to remember the complete Raft log forever. Instead, you'll modify Raft and kvserver to cooperate to save space: from time to time kvserver will persistently store a "snapshot" of its current state, and Raft will discard log entries that precede the snapshot. When a server restarts (or falls far behind the leader and must catch up), the server first installs a snapshot and then replays log entries from after the point at which the snapshot was created. Section 7 of the [Raft paper][raftpaper] outlines the scheme; you will have to design the details. The tester passes a `maxraftstate` to the `KvServer::new` indicating the maximum allowed size of your persistent Raft state in bytes (including the log, but not including snapshots). You should check the size of Raft state and when Raft state size is approaching this threshold, it should save a snapshot, and tell the Raft library that it has snapshotted, so that Raft can discard old log entries. The `maxraftstate` is a `Option` and you do not have to snapshot when it is `None`. First you should modify the Raft implement to accept a compaction request and discard entries before the given index, and continue operating while storing only log entries after that index. The tests from lab2:raft should still pass. Then you should modify the kvserver so that it can hands snapshots to Raft and request compaction when Raft state grows too large. The snapshots should be saved in `raft::Persister` Here are some hints on this part: - You are allowed to add methods to your Raft so that kvserver can manage the process of trimming the Raft log and manage kvserver snapshots. - You can test your Raft and kvserver's ability to operate with a trimmed log, and its ability to re-start from the combination of a kvserver snapshot and persisted Raft state, by running the Lab 3A tests while overriding `maxraftstate` to `Some(1)`. - Think about what should be in the snapshot. You should save new snapshot and restore latest snapshot with `raft::Persister`. - Uncommitted logs can also in snapshots, so your kvserver must still be able to detect duplicated operations under this situation. After that, you should define the `install_snapshot` RPC and the leader should send this RPC when the leader has discarded the log entries the follower needs. When a follower receives an `install_snapshot` RPC, it should send the snapshot to kvserver (maybe in `apply_ch`). After this you should pass all tests in this part. To run all the test in this lab, run `make test_3b`. Here are some hints on this part: - You do not need to send the snapshots in multiple RPCs. Just send the entire snapshot in a single `install_snapshot` RPC and that should be enough for this lab. - You can try `test_snapshot_rpc_3b` first [raftpaper]:https://raft.github.io/raft.pdf ================================================ FILE: courses/dss/raft/build.rs ================================================ fn main() { let includes = &[std::path::PathBuf::from("src/proto")]; let mut protos = Vec::new(); for include in includes { for file in std::fs::read_dir(include).unwrap() { let file = file.unwrap(); if file.file_type().unwrap().is_dir() { continue; } let path = file.path(); if path.extension().unwrap() == "proto" { protos.push(path); } } } prost_build::compile_protos(&protos, includes).unwrap(); for p in protos { println!("cargo:rerun-if-changed={}", p.display()); } } ================================================ FILE: courses/dss/raft/src/kvraft/client.rs ================================================ use std::fmt; use crate::proto::kvraftpb::*; enum Op { Put(String, String), Append(String, String), } pub struct Clerk { pub name: String, pub servers: Vec, // You will have to modify this struct. } impl fmt::Debug for Clerk { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Clerk").field("name", &self.name).finish() } } impl Clerk { pub fn new(name: String, servers: Vec) -> Clerk { // You'll have to add code here. // Clerk { name, servers } crate::your_code_here((name, servers)) } /// fetch the current value for a key. /// returns "" if the key does not exist. /// keeps trying forever in the face of all other errors. // // you can send an RPC with code like this: // if let Some(reply) = self.servers[i].get(args).wait() { /* do something */ } pub fn get(&self, key: String) -> String { // You will have to modify this function. crate::your_code_here(key) } /// shared by Put and Append. // // you can send an RPC with code like this: // let reply = self.servers[i].put_append(args).unwrap(); fn put_append(&self, op: Op) { // You will have to modify this function. crate::your_code_here(op) } pub fn put(&self, key: String, value: String) { self.put_append(Op::Put(key, value)) } pub fn append(&self, key: String, value: String) { self.put_append(Op::Append(key, value)) } } ================================================ FILE: courses/dss/raft/src/kvraft/config.rs ================================================ use std::collections::HashMap; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; use rand::seq::SliceRandom; use crate::kvraft::errors::{Error, Result}; use crate::kvraft::{client, server}; use crate::proto::kvraftpb::*; use crate::proto::raftpb::*; use crate::raft; use crate::raft::persister::*; static ID: AtomicUsize = AtomicUsize::new(300_000); fn uniqstring() -> String { format!("{}", ID.fetch_add(1, Ordering::Relaxed)) } struct Servers { kvservers: Vec>, saved: Vec>, endnames: Vec>, } fn init_logger() { use std::sync::Once; static LOGGER_INIT: Once = Once::new(); LOGGER_INIT.call_once(env_logger::init); } pub struct Config { pub net: labrpc::Network, pub n: usize, servers: Mutex, clerks: Mutex>>, next_client_id: AtomicUsize, maxraftstate: Option, // time at which the Config was created. start: Instant, // begin()/end() statistics // time at which test_test.go called cfg.begin() t0: Mutex, // rpc_total() at start of test rpcs0: AtomicUsize, // number of agreements ops: AtomicUsize, } impl Config { pub fn new(n: usize, unreliable: bool, maxraftstate: Option) -> Config { init_logger(); let servers = Servers { kvservers: vec![None; n], saved: (0..n).map(|_| Arc::new(SimplePersister::new())).collect(), endnames: vec![vec![String::new(); n]; n], }; let cfg = Config { n, net: labrpc::Network::new(), servers: Mutex::new(servers), clerks: Mutex::new(HashMap::new()), // client ids start 1000 above the highest serverid, next_client_id: AtomicUsize::new(n + 1000), maxraftstate, start: Instant::now(), t0: Mutex::new(Instant::now()), rpcs0: AtomicUsize::new(0), ops: AtomicUsize::new(0), }; // create a full set of KV servers. for i in 0..cfg.n { cfg.start_server(i); } cfg.connect_all(); cfg.net.set_reliable(!unreliable); cfg } pub fn op(&self) { self.ops.fetch_add(1, Ordering::Relaxed); } fn rpc_total(&self) -> usize { self.net.total_count() } pub fn check_timeout(&self) { // enforce a two minute real-time limit on each test if self.start.elapsed() > Duration::from_secs(120) { panic!("test took longer than 120 seconds"); } } /// Maximum log size across all servers pub fn log_size(&self) -> usize { let servers = self.servers.lock().unwrap(); let mut logsize = 0; for save in &servers.saved { let n = save.raft_state().len(); if n > logsize { logsize = n; } } logsize } /// Maximum snapshot size across all servers pub fn snapshot_size(&self) -> usize { let mut snapshotsize = 0; let servers = self.servers.lock().unwrap(); for save in &servers.saved { let n = save.snapshot().len(); if n > snapshotsize { snapshotsize = n; } } snapshotsize } /// Attach server i to servers listed in to fn connect(&self, i: usize, to: &[usize], servers: &Servers) { debug!("connect peer {} to {:?}", i, to); // outgoing socket files for j in to { let endname = &servers.endnames[i][*j]; self.net.enable(endname, true); } // incoming socket files for j in to { let endname = &servers.endnames[*j][i]; self.net.enable(endname, true); } } /// Detach server i from the servers listed in from fn disconnect(&self, i: usize, from: &[usize], servers: &Servers) { debug!("disconnect peer {} from {:?}", i, from); // outgoing socket files for j in from { if !servers.endnames[i].is_empty() { let endname = &servers.endnames[i][*j]; self.net.enable(endname, false); } } // incoming socket files for j in from { if !servers.endnames[*j].is_empty() { let endname = &servers.endnames[*j][i]; self.net.enable(endname, false); } } } pub fn all(&self) -> Vec { (0..self.n).collect() } pub fn connect_all(&self) { let servers = self.servers.lock().unwrap(); for i in 0..self.n { self.connect(i, &self.all(), &*servers); } } /// Sets up 2 partitions with connectivity between servers in each partition. pub fn partition(&self, p1: &[usize], p2: &[usize]) { debug!("partition servers into: {:?} {:?}", p1, p2); let servers = self.servers.lock().unwrap(); for i in p1 { self.disconnect(*i, p2, &*servers); self.connect(*i, p1, &*servers); } for i in p2 { self.disconnect(*i, p1, &*servers); self.connect(*i, p2, &*servers); } } // Create a clerk with clerk specific server names. // Give it connections to all of the servers, but for // now enable only connections to servers in to[]. pub fn make_client(&self, to: &[usize]) -> client::Clerk { // a fresh set of ClientEnds. let mut ends = Vec::with_capacity(self.n); let mut endnames = Vec::with_capacity(self.n); for j in 0..self.n { let name = uniqstring(); endnames.push(name.clone()); let cli = self.net.create_client(name.clone()); ends.push(KvClient::new(cli)); self.net.connect(&name, &format!("{}", j)); } ends.shuffle(&mut rand::thread_rng()); let ck_name = uniqstring(); let ck = client::Clerk::new(ck_name.clone(), ends); self.clerks.lock().unwrap().insert(ck_name, endnames); self.next_client_id.fetch_add(1, Ordering::Relaxed); self.connect_client(&ck, to); ck } pub fn delete_client(&self, ck: &client::Clerk) { self.clerks.lock().unwrap().remove(&ck.name); } pub fn connect_client(&self, ck: &client::Clerk, to: &[usize]) { self.connect_client_by_name(&ck.name, to); } pub fn connect_client_by_name(&self, ck_name: &str, to: &[usize]) { debug!("connect_client {:?} to {:?}", ck_name, to); let clerks = self.clerks.lock().unwrap(); let endnames = &clerks[ck_name]; for j in to { let s = &endnames[*j]; self.net.enable(s, true); } } /// Shutdown a server by isolating it pub fn shutdown_server(&self, i: usize) { let mut servers = self.servers.lock().unwrap(); self.disconnect(i, &self.all(), &*servers); // disable client connections to the server. // it's important to do this before creating // the new Persister in saved[i], to avoid // the possibility of the server returning a // positive reply to an Append but persisting // the result in the superseded Persister. self.net.delete_server(&format!("{}", i)); // a fresh persister, in case old instance // continues to update the Persister. // but copy old persister's content so that we always // pass Make() the last persisted state. let p = raft::persister::SimplePersister::new(); p.save_state_and_snapshot(servers.saved[i].raft_state(), servers.saved[i].snapshot()); servers.saved[i] = Arc::new(p); if let Some(kv) = servers.kvservers[i].take() { kv.kill(); } } /// Start a server i. /// If restart servers, first call shutdown_server pub fn start_server(&self, i: usize) { // a fresh set of outgoing ClientEnd names. let mut servers = self.servers.lock().unwrap(); servers.endnames[i] = (0..self.n).map(|_| uniqstring()).collect(); // a fresh set of ClientEnds. let mut ends = Vec::with_capacity(self.n); for (j, name) in servers.endnames[i].iter().enumerate() { let cli = self.net.create_client(name.clone()); ends.push(RaftClient::new(cli)); self.net.connect(name, &format!("{}", j)); } // a fresh persister, so old instance doesn't overwrite // new instance's persisted state. // give the fresh persister a copy of the old persister's // state, so that the spec is that we pass StartKVServer() // the last persisted state. let sp = raft::persister::SimplePersister::new(); sp.save_state_and_snapshot(servers.saved[i].raft_state(), servers.saved[i].snapshot()); let p = Arc::new(sp); servers.saved[i] = p.clone(); let kv = server::KvServer::new(ends, i, Box::new(p), self.maxraftstate); let rf_node = kv.rf.clone(); let kv_node = server::Node::new(kv); servers.kvservers[i] = Some(kv_node.clone()); let mut builder = labrpc::ServerBuilder::new(format!("{}", i)); add_raft_service(rf_node, &mut builder).unwrap(); add_kv_service(kv_node, &mut builder).unwrap(); let srv = builder.build(); self.net.add_server(srv); } pub fn leader(&self) -> Result { let servers = self.servers.lock().unwrap(); for (i, kv) in servers.kvservers.iter().enumerate() { if let Some(kv) = kv { if kv.is_leader() { return Ok(i); } } } Err(Error::NoLeader) } /// Partition servers into 2 groups and put current leader in minority pub fn make_partition(&self) -> (Vec, Vec) { let l = self.leader().unwrap_or(0); let mut p1 = Vec::with_capacity(self.n / 2 + 1); let mut p2 = Vec::with_capacity(self.n / 2); for i in 0..self.n { if i != l { if p1.len() < self.n / 2 + 1 { p1.push(i); } else { p2.push(i); } } } p2.push(l); (p1, p2) } /// Start a Test. /// print the Test message. /// e.g. cfg.begin("Test (2B): RPC counts aren't too high") pub fn begin(&self, description: &str) { println!(); // Force the log starts at a new line. info!("{} ...", description); *self.t0.lock().unwrap() = Instant::now(); self.rpcs0.store(self.rpc_total(), Ordering::Relaxed); self.ops.store(0, Ordering::Relaxed); } /// End a Test -- the fact that we got here means there /// was no failure. /// print the Passed message, /// and some performance numbers. pub fn end(&self) { self.check_timeout(); // real time let t = self.t0.lock().unwrap().elapsed(); // number of Raft peers let npeers = self.n; // number of RPC sends let nrpc = self.rpc_total() - self.rpcs0.load(Ordering::Relaxed); // number of clerk get/put/append calls let nops = self.ops.load(Ordering::Relaxed); info!(" ... Passed --"); info!(" {:?} {} {} {}", t, npeers, nrpc, nops); } } impl Drop for Config { fn drop(&mut self) { let servers = self.servers.lock().unwrap(); for s in servers.kvservers.iter().flatten() { s.kill(); } } } ================================================ FILE: courses/dss/raft/src/kvraft/errors.rs ================================================ use std::{error, fmt, result}; #[derive(Clone, Debug, PartialEq, Eq)] pub enum Error { NoLeader, } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self) } } impl error::Error for Error { fn source(&self) -> Option<&(dyn error::Error + 'static)> { match *self { Error::NoLeader => None, } } } pub type Result = result::Result; ================================================ FILE: courses/dss/raft/src/kvraft/mod.rs ================================================ pub mod client; #[cfg(test)] pub mod config; pub mod errors; pub mod server; #[cfg(test)] mod tests; ================================================ FILE: courses/dss/raft/src/kvraft/server.rs ================================================ use futures::channel::mpsc::unbounded; use crate::proto::kvraftpb::*; use crate::raft; pub struct KvServer { pub rf: raft::Node, me: usize, // snapshot if log grows this big maxraftstate: Option, // Your definitions here. } impl KvServer { pub fn new( servers: Vec, me: usize, persister: Box, maxraftstate: Option, ) -> KvServer { // You may need initialization code here. let (tx, apply_ch) = unbounded(); let rf = raft::Raft::new(servers, me, persister, tx); crate::your_code_here((rf, maxraftstate, apply_ch)) } } impl KvServer { /// Only for suppressing deadcode warnings. #[doc(hidden)] pub fn __suppress_deadcode(&mut self) { let _ = &self.me; let _ = &self.maxraftstate; } } // Choose concurrency paradigm. // // You can either drive the kv server by the rpc framework, // // ```rust // struct Node { server: Arc> } // ``` // // or spawn a new thread runs the kv server and communicate via // a channel. // // ```rust // struct Node { sender: Sender } // ``` #[derive(Clone)] pub struct Node { // Your definitions here. } impl Node { pub fn new(kv: KvServer) -> Node { // Your code here. crate::your_code_here(kv); } /// the tester calls kill() when a KVServer instance won't /// be needed again. you are not required to do anything /// in kill(), but it might be convenient to (for example) /// turn off debug output from this instance. pub fn kill(&self) { // If you want to free some resources by `raft::Node::kill` method, // you should call `raft::Node::kill` here also to prevent resource leaking. // Since the test framework will call kvraft::Node::kill only. // self.server.kill(); // Your code here, if desired. } /// The current term of this peer. pub fn term(&self) -> u64 { self.get_state().term() } /// Whether this peer believes it is the leader. pub fn is_leader(&self) -> bool { self.get_state().is_leader() } pub fn get_state(&self) -> raft::State { // Your code here. raft::State { ..Default::default() } } } #[async_trait::async_trait] impl KvService for Node { // CAVEATS: Please avoid locking or sleeping here, it may jam the network. async fn get(&self, arg: GetRequest) -> labrpc::Result { // Your code here. crate::your_code_here(arg) } // CAVEATS: Please avoid locking or sleeping here, it may jam the network. async fn put_append(&self, arg: PutAppendRequest) -> labrpc::Result { // Your code here. crate::your_code_here(arg) } } ================================================ FILE: courses/dss/raft/src/kvraft/tests.rs ================================================ use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::mpsc; use std::sync::Arc; use std::sync::Mutex; use std::task::Poll; use std::thread; use std::time::{Duration, Instant}; use futures::channel::oneshot; use futures::executor::block_on; use futures::future; use futures::{Future, FutureExt}; use futures_timer::Delay; use rand::{seq::SliceRandom, Rng}; use linearizability::check_operations_timeout; use linearizability::model::Operation; use linearizability::models::{KvInput, KvModel, KvOutput, Op}; use crate::kvraft::client::Clerk; use crate::kvraft::config::Config; /// The tester generously allows solutions to complete elections in one second /// (much more than the paper's range of timeouts). const RAFT_ELECTION_TIMEOUT: Duration = Duration::from_millis(1000); const LINEARIZABILITY_CHECK_TIMEOUT: Duration = Duration::from_millis(1000); // get/put/append that keep counts fn get(cfg: &Config, ck: &Clerk, key: &str) -> String { let v = ck.get(key.to_owned()); cfg.op(); v } fn put(cfg: &Config, ck: &Clerk, key: &str, value: &str) { ck.put(key.to_owned(), value.to_owned()); cfg.op(); } fn append(cfg: &Config, ck: &Clerk, key: &str, value: &str) { ck.append(key.to_owned(), value.to_owned()); cfg.op(); } fn check(cfg: &Config, ck: &Clerk, key: &str, value: &str) { let v = get(cfg, ck, key); if v != value { panic!("get({:?}): expected:\n{:?}\nreceived:\n{:?}", key, value, v); } } // spawn ncli clients and wait until they are all done fn spawn_clients_and_wait( cfg: Arc, ncli: usize, fact: Fact, ) -> impl Future + Send + 'static where Fact: Fn() -> Func + Send + 'static, Func: Fn(usize, &Clerk) + Send + 'static, { let mut cas = Vec::with_capacity(ncli); for cli in 0..ncli { let (tx, rx) = oneshot::channel(); cas.push(rx.map(move |_| { debug!("spawn_clients_and_wait: client {} is done", cli); })); let cfg_ = cfg.clone(); // a client runs the function func and then signals it is done let func = fact(); thread::spawn(move || { let ck = cfg_.make_client(&cfg_.all()); func(cli, &ck); cfg_.delete_client(&ck); tx.send(()) }); } debug!("spawn_clients_and_wait: waiting for clients"); future::join_all(cas).map(|_| ()) } // predict effect of append(k, val) if old value is prev. fn next_value(prev: String, val: &str) -> String { prev + val } // check that for a specific client all known appends are present in a value, // and in order fn check_clnt_appends(clnt: usize, v: String, count: usize) { let mut lastoff = None; for j in 0..count { let wanted = format!("x {} {} y", clnt, j); if let Some(off) = v.find(&wanted) { let off1 = v.rfind(&wanted).unwrap(); assert_eq!(off1, off, "duplicate element {:?} in Append result", wanted); if let Some(lastoff) = lastoff { assert!( off > lastoff, "wrong order for element {:?} in Append result", wanted ); } lastoff = Some(off); } else { panic!( "{:?} missing element {:?} in Append result {:?}", clnt, wanted, v ) } } } // check that all known appends are present in a value, // and are in order for each concurrent client. #[allow(clippy::needless_range_loop)] fn check_concurrent_appends(v: String, counts: &[usize]) { let nclients = counts.len(); for i in 0..nclients { let mut lastoff = None; for j in 0..counts[i] { let wanted = format!("x {} {} y", i, j); if let Some(off) = v.find(&wanted) { let off1 = v.rfind(&wanted).unwrap(); assert_eq!(off1, off, "duplicate element {:?} in Append result", wanted); if let Some(lastoff) = lastoff { assert!( off > lastoff, "wrong order for element {:?} in Append result", wanted ); } lastoff = Some(off); } else { panic!( "{:?} missing element {:?} in Append result {:?}", i, wanted, v ) } } } } // repartition the servers periodically fn partitioner( cfg: Arc, ch: mpsc::Sender, done: Arc, ) -> impl Future + Send + 'static { fn delay(r: u64) -> Delay { Delay::new(RAFT_ELECTION_TIMEOUT + Duration::from_millis(r % 200)) } // Context of the poll_fn. let mut all = cfg.all(); let mut sleep = None; let mut is_parked = false; future::poll_fn(move |cx| { let mut rng = rand::thread_rng(); while done.load(Ordering::Relaxed) == 0 { if !is_parked { all.shuffle(&mut rng); let offset = rng.gen_range(0, cfg.n); cfg.partition(&all[..offset], &all[offset..]); sleep = Some(delay(rng.gen::())); } is_parked = true; let sleep = sleep.as_mut().unwrap(); futures::pin_mut!(sleep); futures::ready!(sleep.poll(cx)); is_parked = false; } ch.send(true).unwrap(); Poll::Ready(()) }) } // Basic test is as follows: one or more clients submitting Append/Get // operations to set of servers for some period of time. After the period is // over, test checks that all appended values are present and in order for a // particular key. If unreliable is set, RPCs may fail. If crash is set, the // servers crash after the period is over and restart. If partitions is set, // the test repartitions the network concurrently with the clients and servers. If // maxraftstate is a positive number, the size of the state for Raft (i.e., log // size) shouldn't exceed 2*maxraftstate. fn generic_test( part: &str, nclients: usize, unreliable: bool, crash: bool, partitions: bool, maxraftstate: Option, ) { let mut title = "Test: ".to_owned(); if unreliable { // the network drops RPC requests and replies. title += "unreliable net, "; } if crash { // peers re-start, and thus persistence must work. title += "restarts, "; } if partitions { // the network may partition title += "partitions, "; } if maxraftstate.is_some() { title += "snapshots, "; } if nclients > 1 { title += "many clients"; } else { title += "one client"; } title = format!("{} ({})", title, part); // 3A or 3B const NSERVERS: usize = 5; let cfg = Arc::new(Config::new(NSERVERS, unreliable, maxraftstate)); cfg.begin(&title); let ck = cfg.make_client(&cfg.all()); let done_partitioner = Arc::new(AtomicUsize::new(0)); let done_clients = Arc::new(AtomicUsize::new(0)); let mut clnt_txs = vec![]; let mut clnt_rxs = vec![]; for _ in 0..nclients { let (tx, rx) = mpsc::channel(); clnt_txs.push(tx); clnt_rxs.push(rx); } for i in 0..3 { let (partitioner_tx, partitioner_rx) = mpsc::channel(); debug!("Iteration {}", i); done_clients.store(0, Ordering::Relaxed); done_partitioner.store(0, Ordering::Relaxed); let clnt_txs_ = clnt_txs.clone(); let cfg_ = cfg.clone(); let done_clients_ = done_clients.clone(); thread::spawn(move || { block_on(async { spawn_clients_and_wait(cfg_.clone(), nclients, move || { let cfg1 = cfg_.clone(); let clnt_txs1 = clnt_txs_.clone(); let done_clients1 = done_clients_.clone(); move |cli, myck| { // TODO: change the closure to a future. let mut j = 0; let mut rng = rand::thread_rng(); let mut last = String::new(); let key = format!("{}", cli); put(&cfg1, myck, &key, &last); while done_clients1.load(Ordering::Relaxed) == 0 { if (rng.gen::() % 1000) < 500 { let nv = format!("x {} {} y", cli, j); debug!("{}: client new append {}", cli, nv); last = next_value(last, &nv); append(&cfg1, myck, &key, &nv); j += 1; } else { debug!("{}: client new get {:?}", cli, key); let v = get(&cfg1, myck, &key); if v != last { panic!( "get wrong value, key {:?}, wanted:\n{:?}\n, got\n{:?}", key, last, v ); } } } clnt_txs1[cli].send(j).unwrap(); } }) .await }) }); if partitions { // Allow the clients to perform some operations without interruption thread::sleep(Duration::from_secs(1)); cfg.net.spawn_poller(partitioner( cfg.clone(), partitioner_tx, done_partitioner.clone(), )); } thread::sleep(Duration::from_secs(5)); // tell clients to quit done_clients.store(1, Ordering::Relaxed); // tell partitioner to quit done_partitioner.store(1, Ordering::Relaxed); if partitions { debug!("wait for partitioner"); partitioner_rx.recv().unwrap(); // reconnect network and submit a request. A client may // have submitted a request in a minority. That request // won't return until that server discovers a new term // has started. cfg.connect_all(); // wait for a while so that we have a new term thread::sleep(RAFT_ELECTION_TIMEOUT); } if crash { debug!("shutdown servers"); for i in 0..NSERVERS { cfg.shutdown_server(i) } // Wait for a while for servers to shutdown, since // shutdown isn't a real crash and isn't instantaneous thread::sleep(RAFT_ELECTION_TIMEOUT); debug!("restart servers"); // crash and re-start all for i in 0..NSERVERS { cfg.start_server(i); } cfg.connect_all(); } debug!("wait for clients"); for (i, clnt_rx) in clnt_rxs.iter().enumerate() { debug!("read from clients {}", i); let j = clnt_rx.recv().unwrap(); if j < 10 { debug!( "Warning: client {} managed to perform only {} put operations in 1 sec?", i, j ); } let key = format!("{}", i); debug!("Check {:?} for client {}", j, i); let v = get(&cfg, &ck, &key); check_clnt_appends(i, v, j); } if let Some(maxraftstate) = maxraftstate { // Check maximum after the servers have processed all client // requests and had time to checkpoint. if cfg.log_size() > 2 * maxraftstate { panic!( "logs were not trimmed ({} > 2*{})", cfg.log_size(), maxraftstate ) } } } cfg.check_timeout(); cfg.end(); } fn generic_test_linearizability( part: &str, nclients: usize, nservers: usize, unreliable: bool, crash: bool, partitions: bool, maxraftstate: Option, ) { let mut title = "Test: ".to_owned(); if unreliable { // the network drops RPC requests and replies. title += "unreliable net, "; } if crash { // peers re-start, and thus persistence must work. title += "restarts, "; } if partitions { // the network may partition title += "partitions, "; } if maxraftstate.is_some() { title += "snapshots, "; } if nclients > 1 { title += "many clients"; } else { title += "one client"; } title = format!("{}, linearizability checks ({})", title, part); // 3A or 3B let cfg = Arc::new(Config::new(nservers, unreliable, maxraftstate)); cfg.begin(&title); let begin = Instant::now(); let operations = Arc::new(Mutex::new(vec![])); let done_partitioner = Arc::new(AtomicUsize::new(0)); let done_clients = Arc::new(AtomicUsize::new(0)); let mut clnt_txs = vec![]; let mut clnt_rxs = vec![]; for _ in 0..nclients { let (tx, rx) = mpsc::channel(); clnt_txs.push(tx); clnt_rxs.push(rx); } for i in 0..3 { let (partitioner_tx, partitioner_rx) = mpsc::channel(); debug!("Iteration {}", i); done_clients.store(0, Ordering::Relaxed); done_partitioner.store(0, Ordering::Relaxed); let clnt_txs_ = clnt_txs.clone(); let cfg_ = cfg.clone(); let done_clients_ = done_clients.clone(); let operations_ = operations.clone(); cfg.net .spawn_poller(spawn_clients_and_wait(cfg.clone(), nclients, move || { let cfg1 = cfg_.clone(); let clnt_txs1 = clnt_txs_.clone(); let done_clients1 = done_clients_.clone(); let operations1 = operations_.clone(); move |cli, myck| { // TODO: change the closure to a future. let mut j = 0; let mut rng = rand::thread_rng(); while done_clients1.load(Ordering::Relaxed) == 0 { let key = format!("{}", rng.gen::() % nclients); let nv = format!("x {} {} y", cli, j); let start = begin.elapsed().as_nanos() as i64; let (inp, out) = if rng.gen::() % 1000 < 500 { append(&cfg1, myck, &key, &nv); j += 1; ( KvInput { op: Op::Append, key, value: nv, }, KvOutput { value: "".to_string(), }, ) } else if rng.gen::() % 1000 < 100 { put(&cfg1, myck, &key, &nv); j += 1; ( KvInput { op: Op::Put, key, value: nv, }, KvOutput { value: "".to_string(), }, ) } else { let v = get(&cfg1, myck, &key); ( KvInput { op: Op::Get, key, value: "".to_string(), }, KvOutput { value: v }, ) }; let end = begin.elapsed().as_nanos() as i64; let op = Operation { input: inp, call: start, output: out, finish: end, }; let mut data = operations1.lock().unwrap(); data.push(op); } clnt_txs1[cli].send(j).unwrap(); } })); if partitions { // Allow the clients to perform some operations without interruption thread::sleep(Duration::from_secs(1)); cfg.net.spawn_poller(partitioner( cfg.clone(), partitioner_tx, done_partitioner.clone(), )); } thread::sleep(Duration::from_secs(5)); // tell clients to quit done_clients.store(1, Ordering::Relaxed); // tell partitioner to quit done_partitioner.store(1, Ordering::Relaxed); if partitions { debug!("wait for partitioner"); partitioner_rx.recv().unwrap(); // reconnect network and submit a request. A client may // have submitted a request in a minority. That request // won't return until that server discovers a new term // has started. cfg.connect_all(); // wait for a while so that we have a new term thread::sleep(RAFT_ELECTION_TIMEOUT); } if crash { debug!("shutdown servers"); for i in 0..nservers { cfg.shutdown_server(i) } // Wait for a while for servers to shutdown, since // shutdown isn't a real crash and isn't instantaneous thread::sleep(RAFT_ELECTION_TIMEOUT); debug!("restart servers"); // crash and re-start all for i in 0..nservers { cfg.start_server(i); } cfg.connect_all(); } // wait for clients. for clnt_rx in &clnt_rxs { clnt_rx.recv().unwrap(); } if let Some(maxraftstate) = maxraftstate { // Check maximum after the servers have processed all client // requests and had time to checkpoint. if cfg.log_size() > 2 * maxraftstate { panic!( "logs were not trimmed ({} > 2*{})", cfg.log_size(), maxraftstate ) } } } cfg.check_timeout(); cfg.end(); if !check_operations_timeout( KvModel {}, Arc::try_unwrap(operations).unwrap().into_inner().unwrap(), LINEARIZABILITY_CHECK_TIMEOUT, ) { panic!("history is not linearizable"); } } #[test] fn test_basic_3a() { // Test: one client (3A) ... generic_test("3A", 1, false, false, false, None) } #[test] fn test_concurrent_3a() { // Test: many clients (3A) ... generic_test("3A", 5, false, false, false, None) } #[test] fn test_unreliable_3a() { // Test: unreliable net, many clients (3A) ... generic_test("3A", 5, true, false, false, None) } #[test] fn test_unreliable_one_key_3a() { let nservers = 3; let cfg = { let cfg = Config::new(nservers, true, None); cfg.begin("Test: concurrent append to same key, unreliable (3A)"); Arc::new(cfg) }; let all = cfg.all(); let ck = cfg.make_client(&all); put(&cfg, &ck, "k", ""); let cfg_ = cfg.clone(); let nclient = 5; let upto = 10; block_on(async { spawn_clients_and_wait(cfg.clone(), nclient, move || { let cfg1 = cfg_.clone(); move |me, myck| { for n in 0..upto { append(&cfg1, myck, "k", &format!("x {} {} y", me, n)); } } }) .await }); let counts = vec![upto; nclient]; let vx = get(&cfg, &ck, "k"); check_concurrent_appends(vx, &counts); cfg.check_timeout(); cfg.end(); } // Submit a request in the minority partition and check that the requests // doesn't go through until the partition heals. The leader in the original // network ends up in the minority partition. #[test] fn test_one_partition_3a() { let nservers = 5; let cfg = Config::new(nservers, false, None); let all = cfg.all(); let ck = cfg.make_client(&all); put(&cfg, &ck, "1", "13"); cfg.begin("Test: progress in majority (3A)"); let (p1, p2) = cfg.make_partition(); cfg.partition(&p1, &p2); // connect ckp1 to p1 let ckp1 = cfg.make_client(&p1); // connect ckp2a to p2 let ckp2a = cfg.make_client(&p2); let ckp2a_name = ckp2a.name.clone(); // connect ckp2b to p2 let ckp2b = cfg.make_client(&p2); let ckp2b_name = ckp2b.name.clone(); put(&cfg, &ckp1, "1", "14"); check(&cfg, &ckp1, "1", "14"); cfg.end(); let (done0_tx, done0_rx) = oneshot::channel::<&'static str>(); let (done1_tx, done1_rx) = oneshot::channel::<&'static str>(); cfg.begin("Test: no progress in minority (3A)"); cfg.net.spawn(future::lazy(move |_| { ckp2a.put("1".to_owned(), "15".to_owned()); done0_tx .send("put") .map_err(|e| { warn!("done0 send failed: {:?}", e); }) .unwrap(); })); let done0_rx = done0_rx.map(|op| { cfg.op(); op }); cfg.net.spawn(future::lazy(move |_| { // different clerk in p2 ckp2b.get("1".to_owned()); done1_tx .send("get") .map_err(|e| { warn!("done0 send failed: {:?}", e); }) .unwrap(); })); let done1_rx = done1_rx.map(|op| { cfg.op(); op }); let timeout = Delay::new(Duration::from_secs(1)); let dones = block_on( future::select(timeout, future::select(done0_rx, done1_rx)).map(|res| match res { future::Either::Left((_, dones)) => dones, future::Either::Right((future::Either::Left((op, _)), _)) => { panic!("{} in minority completed", op.unwrap()) } future::Either::Right((future::Either::Right((op, _)), _)) => { panic!("{} in minority completed", op.unwrap()) } }), ); check(&cfg, &ckp1, "1", "14"); put(&cfg, &ckp1, "1", "16"); check(&cfg, &ckp1, "1", "16"); cfg.end(); cfg.begin("Test: completion after heal (3A)"); cfg.connect_all(); cfg.connect_client_by_name(&ckp2a_name, &all); cfg.connect_client_by_name(&ckp2b_name, &all); thread::sleep(RAFT_ELECTION_TIMEOUT); let timeout = Delay::new(Duration::from_secs(3)); let (timeout, next) = block_on(async { future::select(timeout, dones) .map(|res| match res { future::Either::Left(_) => panic!("put/get did not complete"), future::Either::Right((future::Either::Left((op, next)), timeout)) => { info!("{} completes", op.unwrap()); (timeout, future::Either::Left(next)) } future::Either::Right((future::Either::Right((op, next)), timeout)) => { info!("{} completes", op.unwrap()); (timeout, future::Either::Right(next)) } }) .await }); block_on(async { future::select(timeout, next) .map(|res| match res { future::Either::Left(_) => panic!("put/get did not complete"), future::Either::Right((op, _)) => info!("{} completes", op.unwrap()), }) .await }); check(&cfg, &ck, "1", "15"); cfg.end(); } #[test] fn test_many_partitions_one_client_3a() { // Test: partitions, one client (3A) ... generic_test("3A", 1, false, false, true, None) } #[test] fn test_many_partitions_many_clients_3a() { // Test: partitions, many clients (3A) ... generic_test("3A", 5, false, false, true, None) } #[test] fn test_persist_one_client_3a() { // Test: restarts, one client (3A) ... generic_test("3A", 1, false, true, false, None) } #[test] fn test_persist_concurrent_3a() { // Test: restarts, many clients (3A) ... generic_test("3A", 5, false, true, false, None) } #[test] fn test_persist_concurrent_unreliable_3a() { // Test: unreliable net, restarts, many clients (3A) ... generic_test("3A", 5, true, true, false, None) } #[test] fn test_persist_partition_3a() { // Test: restarts, partitions, many clients (3A) ... generic_test("3A", 5, false, true, true, None) } #[test] fn test_persist_partition_unreliable_3a() { // Test: unreliable net, restarts, partitions, many clients (3A) ... generic_test("3A", 5, true, true, true, None) } #[test] fn test_persist_partition_unreliable_linearizable_3a() { // Test: unreliable net, restarts, partitions, linearizability checks (3A) ... generic_test_linearizability("3A", 15, 7, true, true, true, None) } // if one server falls behind, then rejoins, does it // recover by using the InstallSnapshot RPC? // also checks that majority discards committed log entries // even if minority doesn't respond. #[test] fn test_snapshot_rpc_3b() { let nservers = 3; let maxraftstate = 1000; let cfg = Config::new(nservers, false, Some(maxraftstate)); let all = cfg.all(); let ck = cfg.make_client(&all); cfg.begin("Test: InstallSnapshot RPC (3B)"); put(&cfg, &ck, "a", "A"); check(&cfg, &ck, "a", "A"); // a bunch of puts into the majority partition. cfg.partition(&[0, 1], &[2]); { let ck1 = cfg.make_client(&[0, 1]); for i in 0..50 { put(&cfg, &ck1, &format!("{}", i), &format!("{}", i)); } thread::sleep(RAFT_ELECTION_TIMEOUT); put(&cfg, &ck1, "b", "B"); } // check that the majority partition has thrown away // most of its log entries. if cfg.log_size() > 2 * maxraftstate { panic!( "logs were not trimmed ({} > 2*{})", cfg.log_size(), maxraftstate ); } // now make group that requires participation of // lagging server, so that it has to catch up. cfg.partition(&[0, 2], &[1]); { let ck1 = cfg.make_client(&[0, 2]); put(&cfg, &ck1, "c", "C"); put(&cfg, &ck1, "d", "D"); check(&cfg, &ck1, "a", "A"); check(&cfg, &ck1, "b", "B"); check(&cfg, &ck1, "1", "1"); check(&cfg, &ck1, "49", "49"); } // now everybody cfg.partition(&[0, 1, 2], &[]); put(&cfg, &ck, "e", "E"); check(&cfg, &ck, "c", "C"); check(&cfg, &ck, "e", "E"); check(&cfg, &ck, "1", "1"); cfg.check_timeout(); cfg.end(); } // are the snapshots not too huge? 500 bytes is a generous bound for the // operations we're doing here. #[test] fn test_snapshot_size_3b() { let nservers = 3; let maxraftstate = 1000; let maxsnapshotstate = 500; let cfg = Config::new(nservers, false, Some(maxraftstate)); let all = cfg.all(); let ck = cfg.make_client(&all); cfg.begin("Test: snapshot size is reasonable (3B)"); for _ in 0..200 { put(&cfg, &ck, "x", "0"); check(&cfg, &ck, "x", "0"); put(&cfg, &ck, "x", "1"); check(&cfg, &ck, "x", "1"); } // check that servers have thrown away most of their log entries if cfg.log_size() > 2 * maxraftstate { panic!( "logs were not trimmed ({} > 2*{})", cfg.log_size(), maxraftstate, ) } // check that the snapshots are not unreasonably large if cfg.snapshot_size() > maxsnapshotstate { panic!( "snapshot too large ({} > {})", cfg.snapshot_size(), maxsnapshotstate, ) } cfg.check_timeout(); cfg.end(); } #[test] fn test_snapshot_recover_3b() { // Test: restarts, snapshots, one client (3B) ... generic_test("3B", 1, false, true, false, Some(1000)) } #[test] fn test_snapshot_recover_many_clients_3b() { // Test: restarts, snapshots, many clients (3B) ... generic_test("3B", 20, false, true, false, Some(1000)) } #[test] fn test_snapshot_unreliable_3b() { // Test: unreliable net, snapshots, many clients (3B) ... generic_test("3B", 5, true, false, false, Some(1000)) } #[test] fn test_snapshot_unreliable_recover_3b() { // Test: unreliable net, restarts, snapshots, many clients (3B) ... generic_test("3B", 5, true, true, false, Some(1000)) } #[test] fn test_snapshot_unreliable_recover_concurrent_partition_3b() { // Test: unreliable net, restarts, partitions, snapshots, many clients (3B) ... generic_test("3B", 5, true, true, true, Some(1000)) } #[test] fn test_snapshot_unreliable_recover_concurrent_partition_linearizable_3b() { // Test: unreliable net, restarts, partitions, snapshots, linearizability checks (3B) ... generic_test_linearizability("3B", 15, 7, true, true, true, Some(1000)) } ================================================ FILE: courses/dss/raft/src/lib.rs ================================================ #[allow(unused_imports)] #[macro_use] extern crate log; #[allow(unused_imports)] #[macro_use] extern crate prost_derive; pub mod kvraft; mod proto; pub mod raft; /// A place holder for suppressing unused_variables warning. fn your_code_here(_: T) -> ! { unimplemented!() } ================================================ FILE: courses/dss/raft/src/proto/kvraft.proto ================================================ syntax = "proto3"; package kvraftpb; enum Op { Unknown = 0; Put = 1; Append = 2; } /// Put or Append message PutAppendRequest { string key = 1; string value = 2; // "Put" or "Append" Op op = 3; // You'll have to add definitions here. } message PutAppendReply { bool wrong_leader = 1; string err = 2; } message GetRequest { string key = 1; // You'll have to add definitions here. } message GetReply { bool wrong_leader = 1; string err = 2; string value = 3; } ================================================ FILE: courses/dss/raft/src/proto/mod.rs ================================================ pub mod raftpb { include!(concat!(env!("OUT_DIR"), "/raftpb.rs")); labrpc::service! { service raft { rpc request_vote(RequestVoteArgs) returns (RequestVoteReply); // Your code here if more rpc desired. // rpc xxx(yyy) returns (zzz) } } pub use self::raft::{ add_service as add_raft_service, Client as RaftClient, Service as RaftService, }; } pub mod kvraftpb { include!(concat!(env!("OUT_DIR"), "/kvraftpb.rs")); labrpc::service! { service kv { rpc get(GetRequest) returns (GetReply); rpc put_append(PutAppendRequest) returns (PutAppendReply); // Your code here if more rpc desired. // rpc xxx(yyy) returns (zzz) } } pub use self::kv::{add_service as add_kv_service, Client as KvClient, Service as KvService}; } ================================================ FILE: courses/dss/raft/src/proto/raft.proto ================================================ syntax = "proto3"; package raftpb; // Example RequestVote RPC arguments structure. message RequestVoteArgs { // Your data here (2A, 2B). } // Example RequestVote RPC reply structure. message RequestVoteReply { // Your data here (2A). } ================================================ FILE: courses/dss/raft/src/raft/config.rs ================================================ use std::collections::HashMap; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::{Arc, Mutex}; use std::thread; use std::time::{Duration, Instant}; use futures::channel::mpsc::unbounded; use futures::future; use futures::stream::StreamExt; use rand::Rng; use crate::proto::raftpb::*; use crate::raft; use crate::raft::persister::*; pub const SNAPSHOT_INTERVAL: u64 = 10; fn uniqstring() -> String { static ID: AtomicUsize = AtomicUsize::new(0); format!("{}", ID.fetch_add(1, Ordering::Relaxed)) } /// A log entry. #[derive(Clone, PartialEq, Message)] pub struct Entry { #[prost(uint64, tag = "100")] pub x: u64, } pub struct Storage { // copy of each server's committed entries logs: Vec>, max_index: u64, max_index0: u64, } impl Storage { /// how many servers think a log entry is committed? pub fn n_committed(&self, index: u64) -> (usize, Option) { let mut count = 0; let mut cmd = None; for log in &self.logs { let cmd1 = log.get(&index).cloned(); if cmd1.is_some() { if count > 0 && cmd != cmd1 { panic!( "committed values do not match: index {:?}, {:?}, {:?}", index, cmd, cmd1 ); } count += 1; cmd = cmd1; } } (count, cmd) } } fn init_logger() { use std::sync::Once; static LOGGER_INIT: Once = Once::new(); LOGGER_INIT.call_once(env_logger::init); } pub struct Config { pub net: labrpc::Network, n: usize, // use boxed slice to prohibit grow capacity. pub rafts: Arc]>>>, // whether each server is on the net pub connected: Box<[bool]>, saved: Box<[Arc]>, // the port file names each sends to endnames: Box<[Box<[String]>]>, pub storage: Arc>, // time at which make_config() was called start: Instant, // begin()/end() statistics // time at which test_test.go called cfg.begin() t0: Instant, // rpc_total() at start of test rpcs0: usize, // number of agreements cmds0: usize, } impl Config { pub fn new(n: usize) -> Config { Config::new_with(n, false, false) } pub fn new_with(n: usize, unreliable: bool, snapshot: bool) -> Config { init_logger(); let net = labrpc::Network::new(); net.set_reliable(!unreliable); net.set_long_delays(true); let storage = Storage { logs: vec![HashMap::new(); n], max_index: 0, max_index0: 0, }; let mut saved = vec![]; let mut endnames = vec![]; for _ in 0..n { endnames.push(vec![String::new(); n].into_boxed_slice()); saved.push(Arc::new(SimplePersister::new())); } let mut cfg = Config { net, n, rafts: Arc::new(Mutex::new(vec![None; n].into_boxed_slice())), connected: vec![true; n].into_boxed_slice(), saved: saved.into_boxed_slice(), endnames: endnames.into_boxed_slice(), storage: Arc::new(Mutex::new(storage)), start: Instant::now(), t0: Instant::now(), rpcs0: 0, cmds0: 0, }; for i in 0..n { cfg.start1_ext(i, snapshot); } for i in 0..n { cfg.connect(i); } cfg } pub fn rpc_count(&self, server: usize) -> usize { self.net.count(&format!("{}", server)) } fn rpc_total(&self) -> usize { self.net.total_count() } /// Maximum log size across all servers pub fn log_size(&self) -> usize { self.saved .iter() .map(|s| s.raft_state().len()) .max() .unwrap() } // check that there's exactly one leader. // try a few times in case re-elections are needed. pub fn check_one_leader(&self) -> usize { let mut random = rand::thread_rng(); let mut leaders = HashMap::new(); for _iters in 0..10 { let ms = 450 + (random.gen::() % 100); thread::sleep(Duration::from_millis(ms)); for (i, connected) in self.connected.iter().enumerate() { if *connected { let state = self.rafts.lock().unwrap()[i] .as_ref() .unwrap() .get_state() .clone(); let term = state.term(); let is_leader = state.is_leader(); if is_leader { leaders.entry(term).or_insert_with(Vec::new).push(i); } } } let mut last_term_with_leader = 0; for (term, leaders) in &leaders { if leaders.len() > 1 { panic!("term {} has {:?} (>1) leaders", term, leaders); } if *term > last_term_with_leader { last_term_with_leader = *term; } } if !leaders.is_empty() { return leaders[&last_term_with_leader][0]; } } panic!("expected one leader, got none") } /// check that everyone agrees on the term. pub fn check_terms(&self) -> u64 { let mut term = 0; for (i, connected) in self.connected.iter().enumerate() { if *connected { let xterm = self.rafts.lock().unwrap()[i].as_ref().unwrap().term(); if term == 0 { term = xterm; } else if term != xterm { panic!("servers disagree on term"); } } } term } /// check that there's no leader pub fn check_no_leader(&self) { for (i, connected) in self.connected.iter().enumerate() { if *connected { let is_leader = self.rafts.lock().unwrap()[i].as_ref().unwrap().is_leader(); if is_leader { panic!("expected no leader, but {} claims to be leader", i); } } } } pub fn check_timeout(&self) { // enforce a two minute real-time limit on each test if self.start.elapsed() > Duration::from_secs(120) { panic!("test took longer than 120 seconds"); } } /// how many servers think a log entry is committed? pub fn n_committed(&self, index: u64) -> (usize, Option) { let s = self.storage.lock().unwrap(); s.n_committed(index) } // wait for at least n servers to commit. // but don't wait forever. pub fn wait(&self, index: u64, n: usize, start_term: Option) -> Option { let mut to = Duration::from_millis(10); for _ in 0..30 { let (nd, _) = self.n_committed(index); if nd >= n { break; } thread::sleep(to); if to < Duration::from_secs(1) { to *= 2; } if let Some(start_term) = start_term { let rafts = self.rafts.lock().unwrap(); for r in rafts.iter().flatten() { let term = r.term(); if term > start_term { // someone has moved on // can no longer guarantee that we'll "win" return None; } } } } let (nd, cmd) = self.n_committed(index); if nd < n { panic!("only {} decided for index {}; wanted {}", nd, index, n); } cmd } /// do a complete agreement. /// it might choose the wrong leader initially, /// and have to re-submit after giving up. /// entirely gives up after about 10 seconds. /// indirectly checks that the servers agree on the /// same value, since n_committed() checks this, /// as do the threads that read from applyCh. /// returns index. /// if retry==true, may submit the command multiple /// times, in case a leader fails just after Start(). /// if retry==false, calls start() only once, in order /// to simplify the early Lab 2B tests. pub fn one(&self, cmd: Entry, expected_servers: usize, retry: bool) -> u64 { let t0 = Instant::now(); let mut starts = 0; while t0.elapsed() < Duration::from_secs(10) { // try all the servers, maybe one is the leader. let mut index = None; for _ in 0..self.n { starts = (starts + 1) % self.n; if self.connected[starts] { let rafts = self.rafts.lock().unwrap(); if let Some(ref rf) = &rafts[starts] { match rf.start(&cmd) { Ok((index1, _)) => { index = Some(index1); break; } Err(e) => debug!("start cmd {:?} failed: {:?}", cmd, e), } } } } if let Some(index) = index { // somebody claimed to be the leader and to have // submitted our command; wait a while for agreement. let t1 = Instant::now(); while t1.elapsed() < Duration::from_secs(2) { let (nd, cmd1) = self.n_committed(index); if nd > 0 && nd >= expected_servers { // committed if let Some(cmd2) = cmd1 { if cmd2 == cmd { // and it was the command we submitted. return index; } } } thread::sleep(Duration::from_millis(20)); } if !retry { panic!("one({:?}) failed to reach agreement", cmd); } } else { thread::sleep(Duration::from_millis(50)); } } panic!("one({:?}) failed to reach agreement", cmd); } /// start a Test. /// print the Test message. /// e.g. cfg.begin("Test (2B): RPC counts aren't too high") pub fn begin(&mut self, description: &str) { println!(); // Force the log starts at a new line. info!("{} ...", description); self.t0 = Instant::now(); self.rpcs0 = self.rpc_total(); self.cmds0 = 0; let mut s = self.storage.lock().unwrap(); s.max_index0 = s.max_index; } /// end a Test -- the fact that we got here means there was no failure. /// print the Passed message, and some performance numbers. pub fn end(&self) { self.check_timeout(); // real time let t = self.t0.elapsed(); // number of Raft peers let npeers = self.n; // number of RPC sends let nrpc = self.rpc_total() - self.rpcs0; // number of Raft agreements reported let s = self.storage.lock().unwrap(); let ncmds = s.max_index - s.max_index0; info!(" ... Passed --"); info!(" {:?} {} {} {}", t, npeers, nrpc, ncmds); } /// start or re-start a Raft. /// if one already exists, "kill" it first. /// allocate new outgoing port file names, and a new /// state persister, to isolate previous instance of /// this server. since we cannot really kill it. pub fn start1(&mut self, i: usize) { self.start1_ext(i, false); } pub fn start1_snapshot(&mut self, i: usize) { self.start1_ext(i, true); } fn start1_ext(&mut self, i: usize, snapshot: bool) { self.crash1(i); // a fresh set of outgoing ClientEnd names. // so that old crashed instance's ClientEnds can't send. self.endnames[i] = vec![String::new(); self.n].into_boxed_slice(); for j in 0..self.n { self.endnames[i][j] = uniqstring(); } // a fresh set of ClientEnds. let mut clients = Vec::with_capacity(self.n); for (j, name) in self.endnames[i].iter().enumerate() { let cli = self.net.create_client(name.to_string()); let client = RaftClient::new(cli); clients.push(client); self.net.connect(name, &format!("{}", j)); } let (tx, apply_ch) = unbounded(); let rf = raft::Raft::new(clients, i, Box::new(self.saved[i].clone()), tx); let node = raft::Node::new(rf); self.rafts.lock().unwrap()[i] = Some(node.clone()); // listen to messages from Raft indicating newly committed messages. let storage = self.storage.clone(); let rafts = self.rafts.clone(); let apply = apply_ch.for_each(move |cmd: raft::ApplyMsg| match cmd { raft::ApplyMsg::Command { data, index } => { // debug!("apply {}", index); let entry = labcodec::decode(&data).expect("committed command is not an entry"); let mut s = storage.lock().unwrap(); for (j, log) in s.logs.iter().enumerate() { if let Some(old) = log.get(&index) { if *old != entry { // some server has already committed a different value for this entry! panic!( "commit index={:?} server={:?} {:?} != server={:?} {:?}", index, i, entry, j, old ); } } } let log = &mut s.logs[i]; if index > 1 && log.get(&(index - 1)).is_none() { panic!("server {} apply out of order {}", i, index); } log.insert(index, entry); if index > s.max_index { s.max_index = index; } if snapshot && (index + 1) % SNAPSHOT_INTERVAL == 0 { rafts.lock().unwrap()[i] .as_ref() .unwrap() .snapshot(index, &data); } future::ready(()) } raft::ApplyMsg::Snapshot { data, index, term } if snapshot => { // debug!("install snapshot {}", index); if rafts.lock().unwrap()[i] .as_ref() .unwrap() .cond_install_snapshot(term, index, &data) { let mut s = storage.lock().unwrap(); let log = &mut s.logs[i]; log.clear(); let entry = labcodec::decode(&data).unwrap(); log.insert(index, entry); } future::ready(()) } // ignore other types of ApplyMsg _ => future::ready(()), }); self.net.spawn_poller(apply); let mut builder = labrpc::ServerBuilder::new(format!("{}", i)); raft::add_raft_service(node, &mut builder).unwrap(); let srv = builder.build(); self.net.add_server(srv); } /// shut down a Raft server but save its persistent state. pub fn crash1(&mut self, i: usize) { self.disconnect(i); // disable client connections to the server. self.net.delete_server(&format!("{}", i)); // a fresh persister, in case old instance // continues to update the Persister. // but copy old persister's content so that we always // pass Make() the last persisted state. let raft_state = self.saved[i].raft_state(); let snapshot = self.saved[i].snapshot(); let p = SimplePersister::new(); p.save_state_and_snapshot(raft_state, snapshot); self.saved[i] = Arc::new(p); if let Some(rf) = self.rafts.lock().unwrap()[i].take() { rf.kill(); } } /// detach server i from the net. pub fn disconnect(&mut self, i: usize) { debug!("disconnect({})", i); self.connected[i] = false; // outgoing ClientEnds for endname in &*self.endnames[i] { self.net.enable(endname, false); } // incoming ClientEnds for names in &*self.endnames { let endname = &names[i]; self.net.enable(endname, false); } } /// attach server i to the net. pub fn connect(&mut self, i: usize) { debug!("connect({})", i); self.connected[i] = true; // outgoing ClientEnds for (j, connected) in self.connected.iter().enumerate() { if *connected { let endname = &*self.endnames[i][j]; self.net.enable(endname, true); } } // incoming ClientEnds for (j, connected) in self.connected.iter().enumerate() { if *connected { let endname = &*self.endnames[j][i]; self.net.enable(endname, true); } } } } impl Drop for Config { fn drop(&mut self) { if let Ok(rafts) = self.rafts.try_lock() { for r in rafts.iter().flatten() { r.kill(); } } // FIXME: we should not panic in a drop method. self.check_timeout(); } } ================================================ FILE: courses/dss/raft/src/raft/errors.rs ================================================ use std::{error, fmt, result}; #[derive(Clone, Debug, PartialEq, Eq)] pub enum Error { Encode(labcodec::EncodeError), Decode(labcodec::DecodeError), Rpc(labrpc::Error), NotLeader, } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self) } } impl error::Error for Error { fn source(&self) -> Option<&(dyn error::Error + 'static)> { match *self { Error::Encode(ref e) => Some(e), Error::Decode(ref e) => Some(e), Error::Rpc(ref e) => Some(e), _ => None, } } } pub type Result = result::Result; ================================================ FILE: courses/dss/raft/src/raft/mod.rs ================================================ use std::sync::mpsc::{sync_channel, Receiver}; use std::sync::Arc; use futures::channel::mpsc::UnboundedSender; #[cfg(test)] pub mod config; pub mod errors; pub mod persister; #[cfg(test)] mod tests; use self::errors::*; use self::persister::*; use crate::proto::raftpb::*; /// As each Raft peer becomes aware that successive log entries are committed, /// the peer should send an `ApplyMsg` to the service (or tester) on the same /// server, via the `apply_ch` passed to `Raft::new`. pub enum ApplyMsg { Command { data: Vec, index: u64, }, // For 2D: Snapshot { data: Vec, term: u64, index: u64, }, } /// State of a raft peer. #[derive(Default, Clone, Debug)] pub struct State { pub term: u64, pub is_leader: bool, } impl State { /// The current term of this peer. pub fn term(&self) -> u64 { self.term } /// Whether this peer believes it is the leader. pub fn is_leader(&self) -> bool { self.is_leader } } // A single Raft peer. pub struct Raft { // RPC end points of all peers peers: Vec, // Object to hold this peer's persisted state persister: Box, // this peer's index into peers[] me: usize, state: Arc, // Your data here (2A, 2B, 2C). // Look at the paper's Figure 2 for a description of what // state a Raft server must maintain. } impl Raft { /// the service or tester wants to create a Raft server. the ports /// of all the Raft servers (including this one) are in peers. this /// server's port is peers[me]. all the servers' peers arrays /// have the same order. persister is a place for this server to /// save its persistent state, and also initially holds the most /// recent saved state, if any. apply_ch is a channel on which the /// tester or service expects Raft to send ApplyMsg messages. /// This method must return quickly. pub fn new( peers: Vec, me: usize, persister: Box, apply_ch: UnboundedSender, ) -> Raft { let raft_state = persister.raft_state(); // Your initialization code here (2A, 2B, 2C). let mut rf = Raft { peers, persister, me, state: Arc::default(), }; // initialize from state persisted before a crash rf.restore(&raft_state); crate::your_code_here((rf, apply_ch)) } /// save Raft's persistent state to stable storage, /// where it can later be retrieved after a crash and restart. /// see paper's Figure 2 for a description of what should be persistent. fn persist(&mut self) { // Your code here (2C). // Example: // labcodec::encode(&self.xxx, &mut data).unwrap(); // labcodec::encode(&self.yyy, &mut data).unwrap(); // self.persister.save_raft_state(data); } /// restore previously persisted state. fn restore(&mut self, data: &[u8]) { if data.is_empty() { // bootstrap without any state? } // Your code here (2C). // Example: // match labcodec::decode(data) { // Ok(o) => { // self.xxx = o.xxx; // self.yyy = o.yyy; // } // Err(e) => { // panic!("{:?}", e); // } // } } /// example code to send a RequestVote RPC to a server. /// server is the index of the target server in peers. /// expects RPC arguments in args. /// /// The labrpc package simulates a lossy network, in which servers /// may be unreachable, and in which requests and replies may be lost. /// This method sends a request and waits for a reply. If a reply arrives /// within a timeout interval, This method returns Ok(_); otherwise /// this method returns Err(_). Thus this method may not return for a while. /// An Err(_) return can be caused by a dead server, a live server that /// can't be reached, a lost request, or a lost reply. /// /// This method is guaranteed to return (perhaps after a delay) *except* if /// the handler function on the server side does not return. Thus there /// is no need to implement your own timeouts around this method. /// /// look at the comments in ../labrpc/src/lib.rs for more details. fn send_request_vote( &self, server: usize, args: RequestVoteArgs, ) -> Receiver> { // Your code here if you want the rpc becomes async. // Example: // ``` // let peer = &self.peers[server]; // let peer_clone = peer.clone(); // let (tx, rx) = channel(); // peer.spawn(async move { // let res = peer_clone.request_vote(&args).await.map_err(Error::Rpc); // tx.send(res); // }); // rx // ``` let (tx, rx) = sync_channel::>(1); crate::your_code_here((server, args, tx, rx)) } fn start(&self, command: &M) -> Result<(u64, u64)> where M: labcodec::Message, { let index = 0; let term = 0; let is_leader = true; let mut buf = vec![]; labcodec::encode(command, &mut buf).map_err(Error::Encode)?; // Your code here (2B). if is_leader { Ok((index, term)) } else { Err(Error::NotLeader) } } fn cond_install_snapshot( &mut self, last_included_term: u64, last_included_index: u64, snapshot: &[u8], ) -> bool { // Your code here (2D). crate::your_code_here((last_included_term, last_included_index, snapshot)); } fn snapshot(&mut self, index: u64, snapshot: &[u8]) { // Your code here (2D). crate::your_code_here((index, snapshot)); } } impl Raft { /// Only for suppressing deadcode warnings. #[doc(hidden)] pub fn __suppress_deadcode(&mut self) { let _ = self.start(&0); let _ = self.cond_install_snapshot(0, 0, &[]); self.snapshot(0, &[]); let _ = self.send_request_vote(0, Default::default()); self.persist(); let _ = &self.state; let _ = &self.me; let _ = &self.persister; let _ = &self.peers; } } // Choose concurrency paradigm. // // You can either drive the raft state machine by the rpc framework, // // ```rust // struct Node { raft: Arc> } // ``` // // or spawn a new thread runs the raft state machine and communicate via // a channel. // // ```rust // struct Node { sender: Sender } // ``` #[derive(Clone)] pub struct Node { // Your code here. } impl Node { /// Create a new raft service. pub fn new(raft: Raft) -> Node { // Your code here. crate::your_code_here(raft) } /// the service using Raft (e.g. a k/v server) wants to start /// agreement on the next command to be appended to Raft's log. if this /// server isn't the leader, returns [`Error::NotLeader`]. otherwise start /// the agreement and return immediately. there is no guarantee that this /// command will ever be committed to the Raft log, since the leader /// may fail or lose an election. even if the Raft instance has been killed, /// this function should return gracefully. /// /// the first value of the tuple is the index that the command will appear /// at if it's ever committed. the second is the current term. /// /// This method must return without blocking on the raft. pub fn start(&self, command: &M) -> Result<(u64, u64)> where M: labcodec::Message, { // Your code here. // Example: // self.raft.start(command) crate::your_code_here(command) } /// The current term of this peer. pub fn term(&self) -> u64 { // Your code here. // Example: // self.raft.term crate::your_code_here(()) } /// Whether this peer believes it is the leader. pub fn is_leader(&self) -> bool { // Your code here. // Example: // self.raft.leader_id == self.id crate::your_code_here(()) } /// The current state of this peer. pub fn get_state(&self) -> State { State { term: self.term(), is_leader: self.is_leader(), } } /// the tester calls kill() when a Raft instance won't be /// needed again. you are not required to do anything in /// kill(), but it might be convenient to (for example) /// turn off debug output from this instance. /// In Raft paper, a server crash is a PHYSICAL crash, /// A.K.A all resources are reset. But we are simulating /// a VIRTUAL crash in tester, so take care of background /// threads you generated with this Raft Node. pub fn kill(&self) { // Your code here, if desired. } /// A service wants to switch to snapshot. /// /// Only do so if Raft hasn't have more recent info since it communicate /// the snapshot on `apply_ch`. pub fn cond_install_snapshot( &self, last_included_term: u64, last_included_index: u64, snapshot: &[u8], ) -> bool { // Your code here. // Example: // self.raft.cond_install_snapshot(last_included_term, last_included_index, snapshot) crate::your_code_here((last_included_term, last_included_index, snapshot)); } /// The service says it has created a snapshot that has all info up to and /// including index. This means the service no longer needs the log through /// (and including) that index. Raft should now trim its log as much as /// possible. pub fn snapshot(&self, index: u64, snapshot: &[u8]) { // Your code here. // Example: // self.raft.snapshot(index, snapshot) crate::your_code_here((index, snapshot)); } } #[async_trait::async_trait] impl RaftService for Node { // example RequestVote RPC handler. // // CAVEATS: Please avoid locking or sleeping here, it may jam the network. async fn request_vote(&self, args: RequestVoteArgs) -> labrpc::Result { // Your code here (2A, 2B). crate::your_code_here(args) } } ================================================ FILE: courses/dss/raft/src/raft/persister.rs ================================================ //! Support for Raft and kvraft to save persistent //! Raft state (log &c) and k/v server snapshots. //! //! we will use the original persister.rs to test your code for grading. //! so, while you can modify this code to help you debug, please //! test with the original before submitting. use std::sync::{Arc, Mutex}; pub trait Persister: Send + 'static { fn raft_state(&self) -> Vec; fn save_raft_state(&self, state: Vec); fn save_state_and_snapshot(&self, state: Vec, snapshot: Vec); fn snapshot(&self) -> Vec; } impl Persister for Box { fn raft_state(&self) -> Vec { (**self).raft_state() } fn save_raft_state(&self, state: Vec) { (**self).save_raft_state(state) } fn save_state_and_snapshot(&self, state: Vec, snapshot: Vec) { (**self).save_state_and_snapshot(state, snapshot) } fn snapshot(&self) -> Vec { (**self).snapshot() } } impl Persister for Arc { fn raft_state(&self) -> Vec { (**self).raft_state() } fn save_raft_state(&self, state: Vec) { (**self).save_raft_state(state) } fn save_state_and_snapshot(&self, state: Vec, snapshot: Vec) { (**self).save_state_and_snapshot(state, snapshot) } fn snapshot(&self) -> Vec { (**self).snapshot() } } #[derive(Default)] pub struct SimplePersister { states: Mutex<( Vec, // raft state Vec, // snapshot )>, } impl SimplePersister { pub fn new() -> SimplePersister { SimplePersister { states: Mutex::default(), } } } impl Persister for SimplePersister { fn raft_state(&self) -> Vec { self.states.lock().unwrap().0.clone() } fn save_raft_state(&self, state: Vec) { self.states.lock().unwrap().0 = state; } fn save_state_and_snapshot(&self, state: Vec, snapshot: Vec) { self.states.lock().unwrap().0 = state; self.states.lock().unwrap().1 = snapshot; } fn snapshot(&self) -> Vec { self.states.lock().unwrap().1.clone() } } #[cfg(test)] mod tests { use super::*; #[test] fn test_object_safety() { let sp = SimplePersister::new(); sp.save_raft_state(vec![111]); let obj: Box = Box::new(sp); assert_eq!(obj.raft_state(), vec![111]); obj.save_state_and_snapshot(vec![222], vec![123]); assert_eq!(obj.raft_state(), vec![222]); assert_eq!(obj.snapshot(), vec![123]); let cloneable_obj: Arc = Arc::new(obj); assert_eq!(cloneable_obj.raft_state(), vec![222]); assert_eq!(cloneable_obj.snapshot(), vec![123]); let cloneable_obj_ = cloneable_obj.clone(); cloneable_obj.save_raft_state(vec![233]); assert_eq!(cloneable_obj_.raft_state(), vec![233]); assert_eq!(cloneable_obj_.snapshot(), vec![123]); let sp = SimplePersister::new(); let obj: Arc = Arc::new(sp); let _box_obj: Box = Box::new(obj); } } ================================================ FILE: courses/dss/raft/src/raft/tests.rs ================================================ #![allow(clippy::identity_op)] use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::mpsc::{channel, Sender}; use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; use futures::channel::oneshot; use futures::executor::block_on; use futures::future; use rand::{rngs::ThreadRng, Rng}; use crate::raft::config::{Config, Entry, Storage, SNAPSHOT_INTERVAL}; use crate::raft::Node; /// The tester generously allows solutions to complete elections in one second /// (much more than the paper's range of timeouts). const RAFT_ELECTION_TIMEOUT: Duration = Duration::from_millis(1000); fn random_entry(rnd: &mut ThreadRng) -> Entry { Entry { x: rnd.gen::(), } } #[test] fn test_initial_election_2a() { let servers = 3; let mut cfg = Config::new(servers); cfg.begin("Test (2A): initial election"); // is a leader elected? cfg.check_one_leader(); // sleep a bit to avoid racing with followers learning of the // election, then check that all peers agree on the term. thread::sleep(Duration::from_millis(50)); let term1 = cfg.check_terms(); // does the leader+term stay the same if there is no network failure? thread::sleep(2 * RAFT_ELECTION_TIMEOUT); let term2 = cfg.check_terms(); if term1 != term2 { warn!("warning: term changed even though there were no failures") } // there should still be a leader. cfg.check_one_leader(); cfg.end(); } #[test] fn test_reelection_2a() { let servers = 3; let mut cfg = Config::new(servers); cfg.begin("Test (2A): election after network failure"); let leader1 = cfg.check_one_leader(); // if the leader disconnects, a new one should be elected. cfg.disconnect(leader1); cfg.check_one_leader(); // if the old leader rejoins, that shouldn't // disturb the new leader. cfg.connect(leader1); let leader2 = cfg.check_one_leader(); // if there's no quorum, no leader should // be elected. cfg.disconnect(leader2); cfg.disconnect((leader2 + 1) % servers); thread::sleep(2 * RAFT_ELECTION_TIMEOUT); cfg.check_no_leader(); // if a quorum arises, it should elect a leader. cfg.connect((leader2 + 1) % servers); cfg.check_one_leader(); // re-join of last node shouldn't prevent leader from existing. cfg.connect(leader2); cfg.check_one_leader(); cfg.end(); } #[test] fn test_many_election_2a() { let servers = 7; let iters = 10; let mut cfg = Config::new(servers); cfg.begin("Test (2A): multiple elections"); cfg.check_one_leader(); let mut random = rand::thread_rng(); for _ in 0..iters { // disconnect three nodes let i1 = random.gen::() % servers; let i2 = random.gen::() % servers; let i3 = random.gen::() % servers; cfg.disconnect(i1); cfg.disconnect(i2); cfg.disconnect(i3); // either the current leader should still be alive, // or the remaining four should elect a new one. cfg.check_one_leader(); cfg.connect(i1); cfg.connect(i2); cfg.connect(i3); } cfg.check_one_leader(); cfg.end(); } #[test] fn test_basic_agree_2b() { let servers = 5; let mut cfg = Config::new(servers); cfg.begin("Test (2B): basic agreement"); let iters = 3; for index in 1..=iters { let (nd, _) = cfg.n_committed(index); if nd > 0 { panic!("some have committed before start()"); } let xindex = cfg.one(Entry { x: index * 100 }, servers, false); if xindex != index { panic!("got index {} but expected {}", xindex, index); } } cfg.end() } #[test] fn test_fail_agree_2b() { let servers = 3; let mut cfg = Config::new(servers); cfg.begin("Test (2B): agreement despite follower disconnection"); cfg.one(Entry { x: 101 }, servers, false); // follower network disconnection let leader = cfg.check_one_leader(); cfg.disconnect((leader + 1) % servers); // agree despite one disconnected server? cfg.one(Entry { x: 102 }, servers - 1, false); cfg.one(Entry { x: 103 }, servers - 1, false); thread::sleep(RAFT_ELECTION_TIMEOUT); cfg.one(Entry { x: 104 }, servers - 1, false); cfg.one(Entry { x: 105 }, servers - 1, false); // re-connect cfg.connect((leader + 1) % servers); // agree with full set of servers? cfg.one(Entry { x: 106 }, servers, true); thread::sleep(RAFT_ELECTION_TIMEOUT); cfg.one(Entry { x: 107 }, servers, true); cfg.end(); } #[test] fn test_fail_no_agree_2b() { let servers = 5; let mut cfg = Config::new(servers); cfg.begin("Test (2B): no agreement if too many followers disconnect"); cfg.one(Entry { x: 10 }, servers, false); // 3 of 5 followers disconnect let leader = cfg.check_one_leader(); cfg.disconnect((leader + 1) % servers); cfg.disconnect((leader + 2) % servers); cfg.disconnect((leader + 3) % servers); let (index, _) = cfg.rafts.lock().unwrap()[leader] .as_ref() .unwrap() .start(&Entry { x: 20 }) .expect("leader rejected start"); if index != 2 { panic!("expected index 2, got {}", index); } thread::sleep(2 * RAFT_ELECTION_TIMEOUT); let (n, _) = cfg.n_committed(index); if n > 0 { panic!("{} committed but no majority", n); } // repair cfg.connect((leader + 1) % servers); cfg.connect((leader + 2) % servers); cfg.connect((leader + 3) % servers); // the disconnected majority may have chosen a leader from // among their own ranks, forgetting index 2. let leader2 = cfg.check_one_leader(); let (index2, _) = cfg.rafts.lock().unwrap()[leader2] .as_ref() .unwrap() .start(&Entry { x: 30 }) .expect("leader2 rejected start"); if !(2..=3).contains(&index2) { panic!("unexpected index {}", index2); } cfg.one(Entry { x: 1000 }, servers, true); cfg.end(); } #[test] fn test_concurrent_starts_2b() { let servers = 3; let mut cfg = Config::new(servers); cfg.begin("Test (2B): concurrent start()s"); let mut success = false; 'outer: for tried in 0..5 { if tried > 0 { // give solution some time to settle thread::sleep(Duration::from_secs(3)); } let leader = cfg.check_one_leader(); let term = match cfg.rafts.lock().unwrap()[leader] .as_ref() .unwrap() .start(&Entry { x: 1 }) { Err(err) => { warn!("start leader {} meet error {:?}", leader, err); continue; } Ok((_, term)) => term, }; let mut idx_rxs = vec![]; for ii in 0..5 { let (tx, rx) = oneshot::channel(); idx_rxs.push(rx); let node = cfg.rafts.lock().unwrap()[leader].clone().unwrap(); cfg.net.spawn(future::lazy(move |_| { let idx = match node.start(&Entry { x: 100 + ii }) { Err(err) => { warn!("start leader {} meet error {:?}", leader, err); None } Ok((idx, term1)) => { if term1 != term { None } else { Some(idx) } } }; tx.send(idx) .map_err(|e| panic!("send failed: {:?}", e)) .unwrap(); })); } let idxes = block_on(async { future::join_all(idx_rxs) .await .into_iter() .map(|idx_rx| idx_rx.unwrap()) .collect::>() }); for j in 0..servers { let t = cfg.rafts.lock().unwrap()[j].as_ref().unwrap().term(); if t != term { // term changed -- can't expect low RPC counts continue 'outer; } } let mut cmds = vec![]; for index in idxes.into_iter().flatten() { if let Some(cmd) = cfg.wait(index, servers, Some(term)) { cmds.push(cmd.x); } else { // peers have moved on to later terms // so we can't expect all Start()s to // have succeeded continue; } } for ii in 0..5 { let x = 100 + ii; let mut ok = false; for cmd in &cmds { if *cmd == x { ok = true; } } assert!(ok, "cmd {} missing in {:?}", x, cmds) } success = true; break; } assert!(success, "term changed too often"); cfg.end(); } #[test] fn test_rejoin_2b() { let servers = 3; let mut cfg = Config::new(servers); cfg.begin("Test (2B): rejoin of partitioned leader"); cfg.one(Entry { x: 101 }, servers, true); // leader network failure let leader1 = cfg.check_one_leader(); cfg.disconnect(leader1); // make old leader try to agree on some entries let _ = cfg.rafts.lock().unwrap()[leader1] .as_ref() .unwrap() .start(&Entry { x: 102 }); let _ = cfg.rafts.lock().unwrap()[leader1] .as_ref() .unwrap() .start(&Entry { x: 103 }); let _ = cfg.rafts.lock().unwrap()[leader1] .as_ref() .unwrap() .start(&Entry { x: 104 }); // new leader commits, also for index=2 cfg.one(Entry { x: 103 }, 2, true); // new leader network failure let leader2 = cfg.check_one_leader(); cfg.disconnect(leader2); // old leader connected again cfg.connect(leader1); cfg.one(Entry { x: 104 }, 2, true); // all together now cfg.connect(leader2); cfg.one(Entry { x: 105 }, servers, true); cfg.end(); } #[test] fn test_backup_2b() { let servers = 5; let mut cfg = Config::new(servers); cfg.begin("Test (2B): leader backs up quickly over incorrect follower logs"); let mut random = rand::thread_rng(); cfg.one(random_entry(&mut random), servers, true); // put leader and one follower in a partition let leader1 = cfg.check_one_leader(); cfg.disconnect((leader1 + 2) % servers); cfg.disconnect((leader1 + 3) % servers); cfg.disconnect((leader1 + 4) % servers); // submit lots of commands that won't commit for _i in 0..50 { let _ = cfg.rafts.lock().unwrap()[leader1] .as_ref() .unwrap() .start(&random_entry(&mut random)); } thread::sleep(RAFT_ELECTION_TIMEOUT / 2); cfg.disconnect((leader1 + 0) % servers); cfg.disconnect((leader1 + 1) % servers); // allow other partition to recover cfg.connect((leader1 + 2) % servers); cfg.connect((leader1 + 3) % servers); cfg.connect((leader1 + 4) % servers); // lots of successful commands to new group. for _i in 0..50 { cfg.one(random_entry(&mut random), 3, true); } // now another partitioned leader and one follower let leader2 = cfg.check_one_leader(); let mut other = (leader1 + 2) % servers; if leader2 == other { other = (leader2 + 1) % servers; } cfg.disconnect(other); // lots more commands that won't commit for _i in 0..50 { let _ = cfg.rafts.lock().unwrap()[leader2] .as_ref() .unwrap() .start(&random_entry(&mut random)); } thread::sleep(RAFT_ELECTION_TIMEOUT / 2); // bring original leader back to life, for i in 0..servers { cfg.disconnect(i); } cfg.connect((leader1 + 0) % servers); cfg.connect((leader1 + 1) % servers); cfg.connect(other); // lots of successful commands to new group. for _i in 0..50 { cfg.one(random_entry(&mut random), 3, true); } // now everyone for i in 0..servers { cfg.connect(i); } cfg.one(random_entry(&mut random), servers, true); cfg.end(); } #[test] fn test_count_2b() { const SERVERS: usize = 3; fn rpcs(cfg: &Config) -> usize { let mut n: usize = 0; for j in 0..SERVERS { n += cfg.rpc_count(j); } n } let mut cfg = Config::new(SERVERS); cfg.begin("Test (2B): RPC counts aren't too high"); cfg.check_one_leader(); let mut total1 = rpcs(&cfg); if !(1..=30).contains(&total1) { panic!("too many or few RPCs ({}) to elect initial leader", total1); } let mut total2 = 0; let mut success = false; 'outer: for tried in 0..5 { if tried > 0 { // give solution some time to settle thread::sleep(Duration::from_secs(3)); } let leader = cfg.check_one_leader(); total1 = rpcs(&cfg); let iters = 10; let (starti, term) = match cfg.rafts.lock().unwrap()[leader] .as_ref() .unwrap() .start(&Entry { x: 1 }) { Ok((starti, term)) => (starti, term), Err(err) => { warn!("start leader {} meet error {:?}", leader, err); continue; } }; let mut cmds = vec![]; let mut random = rand::thread_rng(); for i in 1..iters + 2 { let x = random.gen::(); cmds.push(x); match cfg.rafts.lock().unwrap()[leader] .as_ref() .unwrap() .start(&Entry { x }) { Ok((index1, term1)) => { if term1 != term { // Term changed while starting continue 'outer; } if starti + i != index1 { panic!("start failed"); } } Err(err) => { warn!("start leader {} meet error {:?}", leader, err); continue 'outer; } } } for i in 1..=iters { if let Some(ix) = cfg.wait(starti + i, SERVERS, Some(term)) { if ix.x != cmds[(i - 1) as usize] { panic!( "wrong value {:?} committed for index {}; expected {:?}", ix, starti + i, cmds ); } } } let mut failed = false; total2 = 0; for j in 0..SERVERS { let t = cfg.rafts.lock().unwrap()[j].as_ref().unwrap().term(); if t != term { // term changed -- can't expect low RPC counts // need to keep going to update total2 failed = true; } total2 += cfg.rpc_count(j); } if failed { continue 'outer; } if total2 - total1 > (iters as usize + 1 + 3) * 3 { panic!("too many RPCs ({}) for {} entries", total2 - total1, iters); } success = true; break; } if !success { panic!("term changed too often"); } thread::sleep(RAFT_ELECTION_TIMEOUT); let mut total3 = 0; for j in 0..SERVERS { total3 += cfg.rpc_count(j); } if total3 - total2 > 3 * 20 { panic!( "too many RPCs ({}) for 1 second of idleness", total3 - total2 ); } cfg.end(); } #[test] fn test_persist1_2c() { let servers = 3; let mut cfg = Config::new(servers); cfg.begin("Test (2C): basic persistence"); cfg.one(Entry { x: 11 }, servers, true); // crash and re-start all for i in 0..servers { cfg.start1(i); } for i in 0..servers { cfg.disconnect(i); cfg.connect(i); } cfg.one(Entry { x: 12 }, servers, true); let leader1 = cfg.check_one_leader(); cfg.disconnect(leader1); cfg.start1(leader1); cfg.connect(leader1); cfg.one(Entry { x: 13 }, servers, true); let leader2 = cfg.check_one_leader(); cfg.disconnect(leader2); cfg.one(Entry { x: 14 }, servers - 1, true); cfg.start1(leader2); cfg.connect(leader2); cfg.wait(4, servers, None); // wait for leader2 to join before killing i3 let i3 = (cfg.check_one_leader() + 1) % servers; cfg.disconnect(i3); cfg.one(Entry { x: 15 }, servers - 1, true); cfg.start1(i3); cfg.connect(i3); cfg.one(Entry { x: 16 }, servers, true); cfg.end(); } #[test] fn test_persist2_2c() { let servers = 5; let mut cfg = Config::new(servers); cfg.begin("Test (2C): more persistence"); let mut index = 1; for _ in 0..5 { cfg.one(Entry { x: 10 + index }, servers, true); index += 1; let leader1 = cfg.check_one_leader(); cfg.disconnect((leader1 + 1) % servers); cfg.disconnect((leader1 + 2) % servers); cfg.one(Entry { x: 10 + index }, servers - 2, true); index += 1; cfg.disconnect((leader1 + 0) % servers); cfg.disconnect((leader1 + 3) % servers); cfg.disconnect((leader1 + 4) % servers); cfg.start1((leader1 + 1) % servers); cfg.start1((leader1 + 2) % servers); cfg.connect((leader1 + 1) % servers); cfg.connect((leader1 + 2) % servers); thread::sleep(RAFT_ELECTION_TIMEOUT); cfg.start1((leader1 + 3) % servers); cfg.connect((leader1 + 3) % servers); cfg.one(Entry { x: 10 + index }, servers - 2, true); index += 1; cfg.connect((leader1 + 4) % servers); cfg.connect((leader1 + 0) % servers); } cfg.one(Entry { x: 1000 }, servers, true); cfg.end(); } #[test] fn test_persist3_2c() { let servers = 3; let mut cfg = Config::new(servers); cfg.begin("Test (2C): partitioned leader and one follower crash, leader restarts"); cfg.one(Entry { x: 101 }, 3, true); let leader = cfg.check_one_leader(); cfg.disconnect((leader + 2) % servers); cfg.one(Entry { x: 102 }, 2, true); cfg.crash1((leader + 0) % servers); cfg.crash1((leader + 1) % servers); cfg.connect((leader + 2) % servers); cfg.start1((leader + 0) % servers); cfg.connect((leader + 0) % servers); cfg.one(Entry { x: 103 }, 2, true); cfg.start1((leader + 1) % servers); cfg.connect((leader + 1) % servers); cfg.one(Entry { x: 104 }, servers, true); cfg.end(); } // Test the scenarios described in Figure 8 of the extended Raft paper. Each // iteration asks a leader, if there is one, to insert a command in the Raft // log. If there is a leader, that leader will fail quickly with a high // probability (perhaps without committing the command), or crash after a while // with low probability (most likey committing the command). If the number of // alive servers isn't enough to form a majority, perhaps start a new server. // The leader in a new term may try to finish replicating log entries that // haven't been committed yet. #[test] fn test_figure_8_2c() { let servers = 5; let mut cfg = Config::new(servers); cfg.begin("Test (2C): Figure 8"); let mut random = rand::thread_rng(); cfg.one(random_entry(&mut random), 1, true); let mut nup = servers; for _iters in 0..1000 { let mut leader = None; for i in 0..servers { let mut rafts = cfg.rafts.lock().unwrap(); if let Some(Some(raft)) = rafts.get_mut(i) { if raft.start(&random_entry(&mut random)).is_ok() { leader = Some(i); } } } if (random.gen::() % 1000) < 100 { let ms = random.gen::() % ((RAFT_ELECTION_TIMEOUT.as_millis() / 2) as u64); thread::sleep(Duration::from_millis(ms)); } else { let ms = random.gen::() % 13; thread::sleep(Duration::from_millis(ms)); } if let Some(leader) = leader { cfg.crash1(leader); nup -= 1; } if nup < 3 { let s = random.gen::() % servers; if cfg.rafts.lock().unwrap().get(s).unwrap().is_none() { cfg.start1(s); cfg.connect(s); nup += 1; } } } for i in 0..servers { if cfg.rafts.lock().unwrap().get(i).unwrap().is_none() { cfg.start1(i); cfg.connect(i); } } cfg.one(random_entry(&mut random), servers, true); cfg.end(); } #[test] fn test_unreliable_agree_2c() { let servers = 5; let cfg = { let mut cfg = Config::new_with(servers, true, false); cfg.begin("Test (2C): unreliable agreement"); Arc::new(cfg) }; let mut dones = vec![]; for iters in 1..50 { for j in 0..4 { let c = cfg.clone(); let (tx, rx) = oneshot::channel(); thread::spawn(move || { c.one( Entry { x: (100 * iters) + j, }, 1, true, ); tx.send(()).map_err(|e| panic!("send failed: {:?}", e)) }); dones.push(rx); } cfg.one(Entry { x: iters }, 1, true); } cfg.net.set_reliable(true); block_on(async { future::join_all(dones) .await .into_iter() .for_each(|done| done.unwrap()); }); cfg.one(Entry { x: 100 }, servers, true); cfg.end(); } #[test] fn test_figure_8_unreliable_2c() { let servers = 5; let mut cfg = Config::new_with(servers, true, false); cfg.begin("Test (2C): Figure 8 (unreliable)"); let mut random = rand::thread_rng(); cfg.one( Entry { x: random.gen::() % 10000, }, 1, true, ); let mut nup = servers; for iters in 0..1000 { if iters == 200 { cfg.net.set_long_reordering(true); } let mut leader = None; for i in 0..servers { if cfg.rafts.lock().unwrap()[i] .as_ref() .unwrap() .start(&Entry { x: random.gen::() % 10000, }) .is_ok() && cfg.connected[i] { leader = Some(i); } } if (random.gen::() % 1000) < 100 { let ms = random.gen::() % (RAFT_ELECTION_TIMEOUT.as_millis() as u64 / 2); thread::sleep(Duration::from_millis(ms as u64)); } else { let ms = random.gen::() % 13; thread::sleep(Duration::from_millis(ms)); } if let Some(leader) = leader { if (random.gen::() % 1000) < (RAFT_ELECTION_TIMEOUT.as_millis() as usize) / 2 { cfg.disconnect(leader); nup -= 1; } } if nup < 3 { let s = random.gen::() % servers; if !cfg.connected[s] { cfg.connect(s); nup += 1; } } } for i in 0..servers { if !cfg.connected[i] { cfg.connect(i); } } cfg.one( Entry { x: random.gen::() % 10000, }, servers, true, ); cfg.end(); } fn internal_churn(unreliable: bool) { let servers = 5; let mut cfg = Config::new_with(servers, unreliable, false); if unreliable { cfg.begin("Test (2C): unreliable churn") } else { cfg.begin("Test (2C): churn") } let stop = Arc::new(AtomicUsize::new(0)); // create concurrent clients // TODO: change it a future fn cfn( me: usize, stop_clone: Arc, tx: Sender>>, rafts: Arc]>>>, storage: Arc>, ) { let mut values = vec![]; while stop_clone.load(Ordering::SeqCst) == 0 { let mut random = rand::thread_rng(); let x = random.gen::(); let mut index: i64 = -1; let mut ok = false; // try them all, maybe one of them is a leader let rafts: Vec<_> = rafts.lock().unwrap().iter().cloned().collect(); for raft in &rafts { match raft { Some(rf) => { match rf.start(&Entry { x }) { Ok((index1, _)) => { index = index1 as i64; ok = true; } Err(_) => continue, }; } None => continue, } } if ok { // maybe leader will commit our value, maybe not. // but don't wait forever. for to in &[10, 20, 50, 100, 200] { let (nd, cmd) = storage.lock().unwrap().n_committed(index as u64); if nd > 0 { match cmd { Some(xx) => { if xx.x == x { values.push(xx.x); } } None => panic!("wrong command type"), } break; } thread::sleep(Duration::from_millis(*to)); } } else { thread::sleep(Duration::from_millis((79 + me * 17) as u64)); } } if !values.is_empty() { tx.send(Some(values)).unwrap(); } else { tx.send(None).unwrap(); } } let ncli = 3; let mut nrec = vec![]; for i in 0..ncli { let stop_clone = stop.clone(); let (tx, rx) = channel(); let storage = cfg.storage.clone(); let rafts = cfg.rafts.clone(); thread::spawn(move || { cfn(i, stop_clone, tx, rafts, storage); }); nrec.push(rx); } let mut random = rand::thread_rng(); for _iters in 0..20 { if (random.gen::() % 1000) < 200 { let i = random.gen::() % servers; cfg.disconnect(i); } if (random.gen::() % 1000) < 500 { let i = random.gen::() % servers; if cfg.rafts.lock().unwrap().get(i).unwrap().is_none() { cfg.start1(i); } cfg.connect(i); } if (random.gen::() % 1000) < 200 { let i = random.gen::() % servers; if cfg.rafts.lock().unwrap().get(i).unwrap().is_some() { cfg.crash1(i); } } // Make crash/restart infrequent enough that the peers can often // keep up, but not so infrequent that everything has settled // down from one change to the next. Pick a value smaller than // the election timeout, but not hugely smaller. thread::sleep((RAFT_ELECTION_TIMEOUT * 7) / 10) } thread::sleep(RAFT_ELECTION_TIMEOUT); cfg.net.set_reliable(true); for i in 0..servers { if cfg.rafts.lock().unwrap().get(i).unwrap().is_none() { cfg.start1(i); } cfg.connect(i); } stop.store(1, Ordering::SeqCst); let mut values = vec![]; for rx in &nrec { let mut vv = rx.recv().unwrap().unwrap(); values.append(&mut vv); } thread::sleep(RAFT_ELECTION_TIMEOUT); let last_index = cfg.one(random_entry(&mut random), servers, true); let mut really = vec![]; for index in 1..=last_index { let v = cfg.wait(index, servers, None).unwrap(); really.push(v.x); } for v1 in &values { let mut ok = false; for v2 in &really { if v1 == v2 { ok = true; } } assert!(ok, "didn't find a value"); } cfg.end() } #[test] fn test_reliable_churn_2c() { internal_churn(false); } #[test] fn test_unreliable_churn_2c() { internal_churn(true); } fn snap_common(name: &str, disconnect: bool, reliable: bool, crash: bool) { const MAX_LOG_SIZE: usize = 2000; let iters = 30; let servers = 3; let mut cfg = Config::new_with(servers, !reliable, true); cfg.begin(name); let mut random = rand::thread_rng(); cfg.one(random_entry(&mut random), servers, true); let mut leader1 = cfg.check_one_leader(); for i in 0..iters { let mut victim = (leader1 + 1) % servers; let mut sender = leader1; if i % 3 == 1 { sender = (leader1 + 1) % servers; victim = leader1; } if disconnect { cfg.disconnect(victim); cfg.one(random_entry(&mut random), servers - 1, true); } if crash { cfg.crash1(victim); cfg.one(random_entry(&mut random), servers - 1, true); } // send enough to get a snapshot for _ in 0..=SNAPSHOT_INTERVAL { let _ = cfg.rafts.lock().unwrap()[sender] .as_ref() .unwrap() .start(&random_entry(&mut random)); } // let applier threads catch up with the Start()'s cfg.one(random_entry(&mut random), servers - 1, true); assert!(cfg.log_size() < MAX_LOG_SIZE, "log size too large"); if disconnect { // reconnect a follower, who maybe behind and // needs to receive a snapshot to catch up. cfg.connect(victim); cfg.one(random_entry(&mut random), servers, true); leader1 = cfg.check_one_leader(); } if crash { cfg.start1_snapshot(victim); cfg.connect(victim); cfg.one(random_entry(&mut random), servers, true); leader1 = cfg.check_one_leader(); } } cfg.end(); } #[test] fn test_snapshot_basic_2d() { snap_common("Test (2D): snapshots basic", false, true, false); } #[test] fn test_snapshot_install_2d() { snap_common( "Test (2D): install snapshots (disconnect)", true, true, false, ); } #[test] fn test_snapshot_install_unreliable_2d() { snap_common( "Test (2D): install snapshots (disconnect+unreliable)", true, false, false, ); } #[test] fn test_snapshot_install_crash_2d() { snap_common("Test (2D): install snapshots (crash)", false, true, true); } #[test] fn test_snapshot_install_unreliable_crash_2d() { snap_common( "Test (2D): install snapshots (unreliable+crash)", false, false, true, ); } ================================================ FILE: courses/rust/.gitignore ================================================ *~ target/ ================================================ FILE: courses/rust/CONTRIBUTING.md ================================================ # Contributing to PNA Rust Contributions of any kind are welcome. File bugs on the [issue tracker], no matter how small. If something in the course didn't make sense to you then it won't make sense to somebody else and needs to be fixed. That includes the language: this course is intended to be accessible to those with modest English-language comprehension. Non-technical words should be simple, and grammar should be easy to follow. General feedback and suggestions can be submitted to the issue tracker or to the #rust-training channel on the [TiKV Slack]. When you see something inconsistent or confusing, consider fixing it directly and sending a pull request. For those looking for something to contribute, on the issue tracker, issues for the Rust course are tagged `p: rust`. The `help wanted` and `good first issue` tags may help you find something interesting. [issue tracker]: https://github.com/pingcap/talent-plan/issues/ [TiKV Slack]: https://join.slack.com/t/tikv-wg/shared_invite/enQtNTUyODE4ODU2MzI0LWVlMWMzMDkyNWE5ZjY1ODAzMWUwZGVhNGNhYTc3MzJhYWE0Y2FjYjliYzY1OWJlYTc4OWVjZWM1NDkwN2QxNDE ## Developing a new project Each project expands the scope of the previous, and builds off of learnings from previous projects. Each project lends itself to being extended by the next section's project. When writing a project, look for steps where the design could be specified in multiple ways, where there are multiple solutions, where there is deeper understanding to be gained, and ask questions formulated to get the reader to think more deeply. Projects should be written to take between 2 - 4 hours to implement. When writing a project, look for optional "extension" steps that teach additional practical subjects, but which either aren't necessary to complete the project or require more time and skill to implement. Extension steps usually go at the end of a project. Project text doesn't link directly to documentation resources containing solutions - students should learn where to get the answers from the previous "building blocks" sections. Project text may include inline links to pages that offer explanatios of terms and concepts. Some subjects are revisited multiple times. In particular it is common for one project to introduce a subject with basic tasks, then the subsequent project to expand on that same subject with deeper tasks. ## Style notes Building blocks pages generally begin with the same encouraging phrase, and project pages generally end with the same encouraging phrase. Headers do not capitalize every word; words after a colon are capitalized: ``` ## Project spec ## Lesson: Tools and good bones ``` In projects, be clear on when the student should start hacking, and what they should be hacking, by writing an imperative statement. Format that command in italics: ``` _Try it now._ ``` If there are project extension sections, the first one is preceeded by a thematic break (`---`). For markdown readability headers are always preceeded by two line breaks. One-paragraph side-notes are in italics and preceeded with "Note:", like `_Note: whatever._` Larger tangents that don't move the project forward are in their own sections, with their own headers, named "Aside: ...". They should be related to the subject matter and be interesting enough to justify the large detour. Internal hyperlinks are relative to the current directory, not absolute. For building blocks exercises, if the description spans multiple paragraphs, begin the description in a paragraph separate from the exercise name: ``` - **Exercise: Write a thread pool**. A [thread pool] runs jobs (functions) on a set of reusable threads, which can be more efficient than spawning a new thread for every job. Create a simple thread pool with the following type signature: ``` ## Maintenace notes Keep the project summary (the `**Task**`, `**Goals**`, etc. text) synced between plan.md and the project description. New documentation files that are not part of a project or building-blocks, and not part of standard top-level project files go in `docs/` to keep the GitHub directory listing clean, and keep the rendered README above "the fold". Miscellaneous files that are not part of the user-visible projcet live in `docs/etc`. ================================================ FILE: courses/rust/README.md ================================================ # Practical Networked Applications in Rust A training course about practical systems software construction in [Rust]. Over a series of projects, you will build a single networked, multithreaded, and asynchronous Rust application. Creating this application, a [key-value database][kv], will provide opportunities to exercise the best of the crate ecosystem, a variety of concurrent data types, the world of async Rust, interesting language features, and important Rust tools. In between projects are small lessons and exercises on the subjects necessary to complete the next project. Subjects covered include: - Structuring and maintaining Rust programs - Applying common tools like [clippy] and [rustfmt] - Best practices in Rust error handling - Serialization with [serde] - Simple log-structured storage, inspired by [bitcask] - Network programming with std and [tokio] - Benchmarking with [criterion] - Fun and foolproof parallel programming with [crossbeam] and more - Asyncronous programming with Rust [futures] - How to learn what you don't know about Rust and find the documentation and crates you need to succeed After completing this course you will have the knowledge and experience to begin writing high performance, reliable, systems software in Rust. And you might discover that doing so is simpler than you expected. _**Important note: Practical Networked Applications in Rust is in an alpha state**. It contains bugs and its scope is limited. If you are taking it now you are brave, but you are also an early tester and your feedback is greatly appreciated. As you are following along please [file issues]. You are also encouraged to fix problems on your own and submit pull requests. See [CONTRIBUTING.md] for details._ **[View the lesson plan][plan]**. ## The goal of this course The goal of this course is to teach new Rust programmers how to build real-world [systems programs][sp], with all the desirable Rust characteristics, including high-performance, reliability, and easy concurrency; and to do so using the best practices that might not be evident to newcomers. Non-goals of this course include teaching installation, syntax, and other Rust basics; teaching basic data structures and algorithms; teaching basic parallel and asynchronous programming concepts; and being a comprehensive resource on the Rust language. That information is easily found in [The Rust Book] and elsewhere. **[View the lesson plan][plan]**. ## Who is this for? Practical Networked Applications in Rust is for novice _Rust_ programmers, but it is not for novice programmers. The primary audience of this course is recent graduates and near-graduates of an undergraduate computer science program who are considering starting a career as a Rust systems programmer. Others will also likely benefit, including experienced developers without systems programming experience. ## Prerequisites Those taking this course should: - [ ] have the equivalent of an undergraduate computer science education, - [ ] have intermediate-level experience in some programming language, - [ ] be comfortable working in the terminal and command line, - [ ] know how to use [git], - [ ] have novice-level experience with [parallel programming] in some language, - [ ] have novice-level experience with [asynchronous programming] in some language, - [ ] have novice-level experience writing code to query a database, [SQL], [NoSQL], [NewSQL], [key-value][kv], or otherwise. - [ ] **have read [The Rust Book] in its entirety**, - [ ] have written _some_ Rust code, including the projects from the book: - [programming a guessing game], - [building a command-line program] and - [building a multithreaded web server]. To reiterate — read [The Rust Book] _before_ taking this course. It is not necessary to have more than novice-level knowledge or experience with Rust, but this course does not teach Rust basics. If you can check all the above boxes then you are ready for this course. If not, we have some [suggestions][pre] for how to learn the prerequisites. Get started now - **[view the lesson plan][plan]**. ## Other courses in this series This course is part of a [series of courses] initiated by [PingCAP] to train students, contributors, new hires, and existing employees in Rust for distributed systems. Those who complete this one may wish to continue to [Distributed Systems in Rust]. ## A PingCAP-specific note This course, combined with [Deep Dive TiKV], and the [Distributed Systems in Rust] course is intended to be enough to enable programmers to meaningfully contribute to [TiKV]. It is most specifically designed to teach those in the Chinese Rust community enough Rust to work on TiKV. The language used is intended to be simple so that those who read only a little English can follow. If you find any of the language difficult to understand please [file issues]. ## Contributing See [CONTRIBUTING.md]. ## License All text and code for this course is dual licensed [CC-BY 4.0] and [MIT]. You may freely reuse any material here under the terms of either or both, at your discretion. [CONTRIBUTING.md]: CONTRIBUTING.md [CC-BY 4.0]: https://opendefinition.org/licenses/cc-by/ [MIT]: https://opensource.org/licenses/MIT [Deep Dive TiKV]: https://tikv.org/deep-dive/introduction/ [Distributed Systems in Rust]: https://github.com/pingcap/talent-plan/tree/master/courses/dss [NewSQL]: https://en.wikipedia.org/wiki/NewSQL [NoSQL]: https://www.thoughtworks.com/insights/blog/nosql-databases-overview [PingCAP]: https://pingcap.com/ [SQL]: https://en.wikipedia.org/wiki/SQL [The Rust Book]: https://doc.rust-lang.org/book/ [The Rust Book]: https://doc.rust-lang.org/stable/book/ [TiKV]: https://github.com/tikv/tikv/ [asynchronous programming]: todo [bitcask]: https://github.com/basho/bitcask/blob/develop/doc/bitcask-intro.pdf [building a command-line program]: https://doc.rust-lang.org/stable/book/ch12-00-an-io-project.html [building a multithreaded web server]: https://doc.rust-lang.org/stable/book/ch20-00-final-project-a-web-server.html [clippy]: https://github.com/rust-lang/rust-clippy/ [criterion]: https://github.com/bheisler/criterion.rs [crossbeam]: https://github.com/crossbeam-rs/crossbeam [file issues]: https://github.com/pingcap/talent-plan/issues/ [futures]: https://docs.rs/futures/0.1.27/futures/ [git]: https://git-scm.com/ [kv]: https://en.wikipedia.org/wiki/Key-value_database [parallel programming]: todo [plan]: ./docs/lesson-plan.md [post-project surveys]: ./docs/lesson-plan.md#user-content-making-pna-rust-better [pre]: ./docs/prerequisites.md [programming a guessing game]: https://doc.rust-lang.org/stable/book/ch02-00-guessing-game-tutorial.html [rustfmt]: https://github.com/rust-lang/rustfmt/ [serde]: https://github.com/serde-rs/serde [series of courses]: https://github.com/pingcap/talent-plan/ [sp]: https://en.wikipedia.org/wiki/System_programming [the roadmap]: ./docs/roadmap.md [tokio]: https://github.com/tokio-rs/tokio [Rust]: https://www.rust-lang.org/ ================================================ FILE: courses/rust/building-blocks/bb-1.md ================================================ # PNA Rust — Building Blocks 1 Let's learn some building blocks! Put your other projects and concerns aside. Take a breath and relax. Here are some fun resources for you to explore. Read all the readings and perform all the exercises. - **[Exercise: Write a Good CLI Program]**. Writing a CLI program in Rust. This is a good warmup to the CLI program you'll be writing in this course, and the techniques used by this author may provide an interesting contrast to those we suggest. Follow along and write the same code. Can you reproduce their results? - **[Reading: The Cargo manifest format]**. A single page in [The Cargo Book], this will give you an idea of how your project can be customized a bit if you so choose. This is a page you will come back to repeatedly as a Rust programmer. - **[Reading: Cargo environment variables]**. Also from The Cargo Book, and also a page that you will see many times in the future. Environment variables are one way that it communicates with rustc, allowing it to set the various [`env!`] macros at build time, in both your program source code and build scripts. It is also a way for scripts and other systems to communicate to Cargo. - **[Reading: Rust API Guidelines: Documentation]**. The Rust project is opinionated about how Rust source is written. This page is on how to document Rust projects, but the whole book is worth reading. These are written by experienced Rust developers, but are in an incomplete state. Note the GitHub organization it belongs to — [`rust-lang-nursery`]. It contains many interesting projects. [Reading: Rust API Guidelines: Documentation]: https://rust-lang-nursery.github.io/api-guidelines/documentation.html [Reading: The Cargo manifest format]: https://doc.rust-lang.org/cargo/reference/manifest.html [Reading: Cargo environment variables]: https://doc.rust-lang.org/cargo/reference/environment-variables.html [The Cargo Book]: https://doc.rust-lang.org/cargo/reference/manifest.html [`env!`]: https://doc.rust-lang.org/std/macro.env.html [`rust-lang-nursery`]: https://github.com/rust-lang-nursery [Reading: The rustup documentation]: https://github.com/rust-lang/rustup.rs/blob/master/README.md [Exercise: Write a Good CLI Program]: https://qiita.com/tigercosmos/items/678f39b1209e60843cc3 ================================================ FILE: courses/rust/building-blocks/bb-2.md ================================================ # PNA Rust — Building Blocks 2 Let's learn some building blocks! Put your other projects and concerns aside. Take a breath and relax. Here are some fun resources for you to explore. Read all the readings and perform all the exercises. - **[Reading: Damn Cool Algorithms: Log structured storage][lss]**. A simple overview of the basic concept of log-structured storage. There are many log-structured storage algorithms, and the particular one described here is not the one you will be using. - **[Reading: The Design and Implementation of a Log-Structured File System][lsfs]**. The influential paper. - **[Reading: Bitcask: A Log-Structured Hash Table for Fast Key/Value Data][bc]**. A simple but effective design for a key-value database, and one that uses log-structured storage. - **[Reading: Error Handling in Rust][e]**. Rust error handling is powerful, and many Rust programmers adore it once they have gotten the hang of it. But it is complex, and has a complex history of trial and error. This is a classic in-depth article on best-practices for error handling in Rust. It is from 2015, and there have been some minor changes to error handling since then, but there is a lot of wisdom in here. The author, [BurntSushi], has done much experimenting with Rust error handling, and is considered an authority on that and [other things]. - **[Reading: `std::collections`][c]**. As a systems programmer it is crucial to know the behavior of a variety of data structures well, if not their implementations. The standard library's `collections` module has a pretty amazing overview of the tradeoffs between a number of the most common collection types in computer science. For this, you only need to read the module docs. - **[Reading: `std::io`][io]**. Again, you need to know your I/O tools, and again the Rust `io` module docs, while not as brilliant reading as the `collections` docs, provide a good overview of your toolset. You only need to read the module docs. - **Exercise: Serialize and deserialize a data structure with `serde` (JSON)**. This exercise and the next two will introduce basic serialization and deserialization with [`serde`]. `serde` serializes data quickly and is easy to use, while also being extensible and expressive. For your serializable data structure, imagine a flat game-playing surface covered in a grid of squares, like a chess board. Imagine you have a game character that every turn may move any number of squares in a single direction. Define a type, `Move` that represents a single move of that character. Derive the [`Debug`] trait so `Move` is easily printable with the `{:?}` format specifier. Write a `main` function that defines a variable, `a`, of type `Move`, serializes it with [`serde`] to a [`File`], then deserializes it back again to a variable, `b`, also of type `Move`. Use [JSON] as the serialization format. Print `a` and `b` with `println!` and the `{:?}` format specifier to verify successful deserialization. Note that the `serde` book has many [examples] to work off of. - **Exercise: Serialize and deserialize a data structure to a buffer with `serde` (RON)**. Do the same as above, except this time, instead of serializing to a `File`, serialize to a `Vec` buffer, and after that try using [RON] instead of JSON as the format. Are there any differences in serialization to a `Vec` instead of a `File`? What about in using the RON crate vs the JSON crate? Convert the `Vec` to `String` with [`str::from_utf8`], unwrapping the result, then print that serialized string representation to see what `Move` looks like serialized to RON. - **Exercise: Serialize and deserialize 1000 data structures with `serde` (BSON)**. This one is slightly different. Where the previous exercises serialized and deserialized a single value to a buffer, in this one serialize 1000 different `Move` values to a single file, back-to-back, then deserialize them again. This time use the [BSON] format. Things to discover here are whether serde automatically maintains the correct file offsets (the "cursor") to deserialize multiple values in sequence, or if you need to parse your own "frames" around each value to define their size, and how to detect that there are no more values to parse at the end of the file. After you've succeeded at serializing and deserializing multiple values to a file, try it again with a `Vec`. Serializing and deserializing generally requires the destination implement the [`Write`] and [`Read`] traits. Does `Vec` implement either or both? What is the behavior of those implementations? You may need to wrap your buffer in wrapper types that implement these traits in order to get the correct behavior — the API docs for the traits list all their implementors in the standard library, and whatever you need will be in there somewhere. [`File`]: https://doc.rust-lang.org/std/fs/struct.File.html [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html [BSON]: https://github.com/zonyitoo/bson-rs [RON]: https://github.com/ron-rs/ron [`str::from_utf8`]: https://doc.rust-lang.org/std/str/fn.from_utf8.html [JSON]: https://github.com/serde-rs/json [`Debug`]: https://doc.rust-lang.org/std/fmt/trait.Debug.html [examples]: https://serde.rs/examples.html [`serde`]: https://serde.rs/ [lss]: http://blog.notdot.net/2009/12/Damn-Cool-Algorithms-Log-structured-storage [lsfs]: https://people.eecs.berkeley.edu/~brewer/cs262/LFS.pdf [io]: https://doc.rust-lang.org/std/io/ [c]: https://doc.rust-lang.org/std/collections/ [e]: https://blog.burntsushi.net/rust-error-handling/ [bc]: https://github.com/basho/bitcask/blob/develop/doc/bitcask-intro.pdf [BurntSushi]: https://github.com/BurntSushi [other things]: https://github.com/BurntSushi/ripgrep ================================================ FILE: courses/rust/building-blocks/bb-3.md ================================================ # PNA Rust — Building Blocks 3 Let's learn some building blocks! Put your other projects and concerns aside. Take a breath and relax. Here are some fun resources for you to explore. Read all the readings and perform all the exercises. - **[Reading: `log` crate API][l]**. The original Rust logging crate. Just read the crate-level documentation (the front page). You may need to click little `[+]` or `[-]` buttons to make the crate docs visible. This will give you an idea about how logging works in Rust. - **[Reading: `slog` crate API][sl]**. Another popular logging crate, designed for "structured logging". Again, just read the crate-level docs, to compare to `log`. You might also want to look at ["Introduction to structured logging with slog"][sli]. - **[Reading: Benefits of Structured Logging vs basic logging][lvsl]**. A StackOverflow discussion about the differences between traditional, text-oriented, line logging and structured logging. - **[Reading: Redis Protocol specification][rp]**. The protocol spec for [Redis], an in-memory key-value store. Think about what their design priorities were. When reading this it also helps to have the Redis [commands] on hand. - **Exercise: Write a Redis ping-pong client and server using `std::io`**. Write a simple client and server that speaks the Redis protocol, with the client issuing [PING] commands and the server responding appropriately. Use the [`std::io`] APIs to read and write bytes directly. Does your client work with an actual Redis server? - **Exercise: Write a Redis ping-pong client and server with serialized messages**. Same as above, but this time define the protocol with types and write a [`serde` data format][df] to indirectly read and write messages through serialization. - **[Reading: Statistically Rigorous Java Performance Evaluation][pe]**. Although it is specifically about Java, and discusses topics relevant to garbage-collected languages, it is a good example of the kind of thinking necessary to create effective benchmarks. [pe]: https://dri.es/files/oopsla07-georges.pdf [df]: https://serde.rs/data-format.html [`std::io`]: https://doc.rust-lang.org/std/io/ [PING]: https://redis.io/commands/ping [commands]: https://redis.io/commands [Redis]: https://redis.io/ [rp]: https://redis.io/topics/protocol [l]: https://docs.rs/log/ [sl]: https://docs.rs/slog/ [sli]: https://github.com/slog-rs/slog/wiki/Introduction-to-structured-logging-with-slog [lvsl]: https://softwareengineering.stackexchange.com/questions/312197/benefits-of-structured-logging-vs-basic-logging ================================================ FILE: courses/rust/building-blocks/bb-4.md ================================================ # PNA Rust — Building Blocks 4 Let's learn some building blocks! Put your other projects and concerns aside. Take a breath and relax. Here are some fun resources for you to explore. Read all the readings and perform all the exercises. Also watch the video. - **[Reading: Fearless Concurrency with Rust][f]**. This is a classic Rust blog post from [Aaron Turon][at] that clearly explains why concurrency is so easy in Rust. The title is also the origin of using the word "fearless" to describe various Rust properties. - **[Reading: What is the difference between concurrency and parallelism?][d]**. This is a 10 second read, but something to keep in mind. The two words are often used interchangably. We'll mostly use the word "concurrent" since it is more general than "parallel". Sometimes we'll use the word "parallel" to be more specific, sometimes because it sounds better… - **[Reading: Rust: A unique perspective][ru]**. An explanation of the dangers of mutable aliasing and how Rust solves the problem. This one is by [Matt Brubeck][mb], from the [Servo] team. - **[Video: Rust Concurrency Explained][ex]**. A more in-depth talk by [Alex Crichton][ac]. Aaron and Alex wrote many of the concurrent data structures in the standard library. Alex has given versions of this talk for years, and it is a pretty great overview of what Rust can do. - **[Reading: `std::sync`][ss]**. Once again, the standard library documentation provides not only good documentation about the library, but about the subject in general. This provides an overview of most of the concurrent types provided by the standard library. - **[Exercise: Basic multithreading][bmt]**. This is a simple multithreading exercise from the [rustlings] project. It is small enough that it can be completed on [play.rust-lang.org]. - **Exercise: Write a thread pool**. A [thread pool] runs jobs (functions) on a set of reusable threads, which can be more efficient than spawning a new thread for every job. Create a simple thread pool with the following type signature: ```rust impl ThreadPool { fn new(threads: u32) -> Result; fn spawn(&self, job: F) where F: FnOnce() + Send + 'static; } ``` The `new` function should immediately spawn `threads` number of threads, and then those threads will wait for jobs to be spawned. When a thread recieves a job, it runs it to completion, then waits for the next job. The [`threadpool`][tp1] crate and Rayon's [`ThreadPool`][tp2] may provide inspiration. - **[Reading: Lock-free vs wait-free concurrency][lf]**. It seems like everybody wants their code to be "lock-free". What's that mean? [lf]: https://rethinkdb.com/blog/lock-free-vs-wait-free-concurrency/ [play.rust-lang.org]: https://play.rust-lang.org/ [tp1]: https://docs.rs/threadpool/1.7.1/threadpool/struct.ThreadPool.html [tp2]: https://docs.rs/rayon/1.0.3/rayon/struct.ThreadPool.html [thread pool]: https://softwareengineering.stackexchange.com/questions/173575/what-is-a-thread-pool#173581 [ss]: https://doc.rust-lang.org/std/sync/index.html [Servo]: https://github.com/servo/servo [mb]: https://github.com/mbrubeck/ [ru]: https://limpet.net/mbrubeck/2019/02/07/rust-a-unique-perspective.html [ac]: https://github.com/alexcrichton/ [ex]: https://www.youtube.com/watch?v=Dbytx0ivH7Q [f]: https://blog.rust-lang.org/2015/04/10/Fearless-Concurrency.html [d]: https://stackoverflow.com/questions/1050222/what-is-the-difference-between-concurrency-and-parallelism#1050257 [at]: https://github.com/aturon [bmt]: https://github.com/rust-lang/rustlings/blob/master/exercises/threads/threads1.rs [rustlings]: https://github.com/rust-lang/rustlings/ ================================================ FILE: courses/rust/building-blocks/bb-5.md ================================================ # PNA Rust — Building Blocks 5 Let's learn some building blocks! Put your other projects and concerns aside. Take a breath and relax. Here are some fun resources for you to explore. Read all the readings and perform all the exercises. Coming soon! ================================================ FILE: courses/rust/docs/etc/notes.md ================================================ # Implementors' notes ## Desired subjects This is a more full list of topics to cover than in the README. - error handling - simple vs. complex, Fail vs StdError, etc - `fn main() -> Result` - `panic!` and unwinding - logging w/ log and slog - how env_logger works? - trees vs maps - async vs sync networking - `std` networking - TCP vs UDP - `reqwest` - blocking HTTP serving w/ Iron - sync file io and solutions to blocking - buffered vs unbuffered i/o - benchmarking, criterion and critcmp, black_box - RUST_BACKTRACE - where to ask questions - futures - tokio - mio? - async/await? - maybe future iterations - Pin? - generic placeholder idiom - let foo: Vec<_> = - construction w/ iterators idiom - semver trick - impl trait, the Into> trick - Rust history, culture, design principles - rustfmt, clippy, configuring both - rust 2018? - we'll just asume rust 2018 and not mention 2015 unless necessary - tools most rust programmers should know - build scripts - protobuf compilation example - getting rustc version - in-depth examples of crates that rely on build scripts - using RUSTFLAGS - debugging - profiling - how not to write Rust (bad practices from other languages) - Ana likes this - variable shadowing - DSTs - configuring clippy / rustfmt - scripting clippy / rustfmt for CI - CI setup - when to use which struct types, impls, ctor patterns, dtors, reprs, padding demo, packed structs, size and alignment in depth, enum implementation and optimizations - importing crates, features, debugging and fixing dependencies, std vs crate philosophy and history, finding crates - how does testing work? - what does `cargo run` do? - cargo / rustc wrapping pattern in depth (ex rustup, `RUSTC_WRAPPER`) - formatting tips, derive Debug in depth, how does `format!` work? - mutable aliasing bugs, how ownership prevents mutable aliasing - Sync / Send, uniq / shared vs immutable / mutable - `Rc` and `Arc`, interior mutability in depth - when to use pass-by-value, the performance impact of moves - reference-bearing structs - sharing vs message passing - thread pools - workspaces - refactoring - https://github.com/altsysrq/proptest - fuzzing - dbg! - shadowing ## Sources - https://pdos.csail.mit.edu/6.824/schedule.html - The MIT distributed systems course this course is inspired by and intended to precede - https://github.com/ferrous-systems/rust-three-days-course - https://github.com/nrc/talks - RustBridge ## Pedagogy - https://launchschool.com/pedagogy - https://launchschool.com/is_this_for_me ## Reading sources - previous reading ideas https://github.com/pingcap/talent-plan/blob/32311e6999a2a5b7db25cd2b4dd96491d5181165/rust/plan.md - http://highscalability.com/blog/2011/1/10/riaks-bitcask-a-log-structured-hash-table-for-fast-keyvalue.html - https://github.com/brson/rust-anthology/blob/master/master-list.md - https://github.com/ctjhoa/rust-learning - https://github.com/basho/bitcask/blob/develop/doc/bitcask-intro.pdf - https://rust-lang-nursery.github.io/failure/ - https://serde.rs/ - https://doc.rust-lang.org/cargo/ - https://medium.com/rabiprasadpadhy/google-spanner-a-newsql-journey-or-beginning-of-the-end-of-the-nosql-era-3785be8e5c38 - https://github.com/Hexilee/async-io-demo - https://stjepang.github.io/2019/01/29/lock-free-rust-crossbeam-in-2019.html - https://limpet.net/mbrubeck/2019/02/07/rust-a-unique-perspective.html - https://doc.rust-lang.org/nomicon/aliasing.html - https://manishearth.github.io/blog/2015/05/17/the-problem-with-shared-mutability/ - https://www.youtube.com/watch?v=9_3krAQtD2k (futures async await) - https://shipilev.net/blog/2014/java-scala-divided-we-fail/ - https://www.internalpointers.com/post/lock-free-multithreading-atomic-operations ## Exercise sources - https://github.com/rust-lang/rustlings - https://exercism.io/tracks/rust - https://doc.rust-lang.org/rust-by-example/index.html ## Subjects to potentially cut - Parallelism section - Formatting lesson - Build time lesson - Collections and iterators ## Grading - automated text-based cheat detection - automated grading of test cases - automated grading of non-unit-test requirements via python script - how to grade freeform answers? ## TODO - do survey of other sources' subject progression - lessons and labs pose questions - have a chinese native identify and remove 'hard' words and phrases - mention somewhere that we're using rust 2018 only, how to verify - change slides.html URLS to link to the hosted file - add more description of how to treat the projects - note that improvements beyond the scope of the project are encouraged - comment them - add TOC to each project - use fail-rs for consistency tests - mention the test names that should be focused on each part of each project - find a way to use specialization via the KvsEngine trait - use imperative "part" titles? "creating" vs "create" - add explanation of "blocking" to parallelism / thread pool project - per readme, make parallelism project "fun and foolproof" - per readme, incorporate critcmp - deleted from readme: - Build scripts and the interaction between build-time and run-time - Insights into inner workings of the language and libraries - to look "under the hood" and understand how and why Rust works like it does - the course can be delivered offline - _lessons_ - focused coverage of subjects required for writing practical software of the type developed in the corresponding projects, including advanced tips, best practices, and deep dives. This are in the form of slides, speaker notes, and short _writeups_. - removed goal of teaching how to find information on your own about rust - it's now an implicit goal - be clearer about crate deps - consistent formatting for crate names (code or not?) (yes, to offset them as crates when not explicitly mentioned) - do better at identifing and explaining the individual problems being solved - add tips for finding documentation and crates - mention mdbook when first linking to a book - rustup doc and cargo doc and where both draw their content from - make project contents more consistent - projects contain sections that are unrelated to the main subject - change project.md to description.md, to get rid of the path stuttering - replace wikipedia, docs.rs, official rust, readings with blog posts, papers and other more specific, harder to find resources - create place to submit solutions - compare criterion to bench - move all links to ends of documents and explain in contributing.md - sort lines of links - how to find the names and descriptions of all lints - consider adding links to project source code somewhere - add note encouraging reading the rustfmt / rustclippy docs - replace "_Note: ..." with "_**Note**: ..." - describe in more depth the final product - put a reminder about building blocks at top of every project - add back-links in some non-intrusive way, somehow - to p1 just add a list of useful Rust cli tools! - sort deps in manifests - after p1 link first uses of crate names to docs.rs - say why we're doing each exercise or diversion - publishing on crates.io - critcmp # Future projects - 5 - use futures + http, use standard http bench tools - 6 - use async/await - 7 - use grpc - 8 - focus on data integrity - 9 - try to match performance of the production components - ? - streaming scan operation with lifetimes and streaming network api # survey - time to complete ================================================ FILE: courses/rust/docs/etc/parallel-diagrams.txt ================================================ Used in p4. Edited with asciiflow.com. --> read/write reqs over time --> --> read/write reqs over time --> thread thread + +--------+--------+--------+--------+ + +--------+ T1 | | R1 | R2 | W1 | W2 | T1 | | R1 | + +--------+--------+--------+--------+ | +-----------------+ T2 | | R2 | --> read/write reqs over time --> | +-----------------+ thread T3 | | W1 | + +--------+ | +-----------------+ T1 | | R1 | T4 | | W2 | | +--------+ + +--------+ T2 | | R2 | | +-----------------+ T3 | | W1 | --> read/write reqs over time --> | +-----------------+ thread T4 | | W2 | + +--------+ + +--------+ T1 | | R1 | | +--------+ --> read/write reqs over time --> T2 | | R2 | thread | +--------+ + +--------+ T3 | | W1 | T1 | | R1 | | +-----------------+ | +--------+ T4 | | W2 | T2 | | R2 | + +--------+ | +--------+ T3 | | W1 | | +--------+ T4 | | W2 | + +--------+ ================================================ FILE: courses/rust/docs/lesson-plan.md ================================================ # PNA Rust Lesson plan A training course about practical systems software construction in Rust. Over a series of projects, you will build a networked [key-value database][kv], with multithreading and asynchronous I/O. In between projects you will study and practice individual subjects necessary to complete the next project. Along the way you will explore multiple designs and their tradeoffs. See [README.md] for the overview, goals, audience, and prerequisites. - [Prerequisites](#user-content-prerequisites) - [Getting the materials](#user-content-getting-the-materials) - [Course structure](#user-content-course-structure) - [Getting help](#user-content-getting-help) - [Making PNA Rust Better](#user-content-making-pna-rust-better) - [Practical Networked Applications in Rust](#user-content-practical-networked-applications-in-rust) - [Building Blocks 1](#user-content-building-blocks-1) - [Project 1: The Rust toolbox](#user-content-project-1-the-rust-toolbox) - [Building Blocks 2](#user-content-building-blocks-2) - [Project 2: Log-structured file I/O](#user-content-project-2-log-structured-file-io) - [Building Blocks 3](#user-content-building-blocks-3) - [Project 3: Synchronous client-server networking](#user-content-project-3-synchronous-client-server-networking) - [Building Blocks 4](#user-content-building-blocks-4) - [Project 4: Concurrency and Parallelism](#user-content-project-4-concurrency-and-parallelism) - [Building Blocks 5](#user-content-building-blocks-5) - [Project 5: Asynchronous programming in Rust](#user-content-project-5-asynchronous-programming-in-rust) - [What next?](#user-content-what-next) ## Prerequisites As [described in the README.md][pre], this is not a course for novice programmers, and there are significant prerequisites. Ensure that you meet them all before proceeding. ## Getting the materials All material for this course is in the > https://github.com/pingcap/talent-plan git repository on GitHub, in the [`rust` subdirectory][rs]. You will want a copy of it on your local computer, particularly for easy access to the conformance tests for each project. ## Course structure The overall arc of the course is defined by a series of coding projects that incrementally introduce new subjects important to systems programming in Rust. Each project extends the previous project, so it is reasonable to simply start your work on each project in the same git repository where you left off on the previous (though you may want to add a [git tag] indicating where the previous project ended). [git tag]: https://git-scm.com/book/en/v2/Git-Basics-Tagging Because building an entire database from scratch while also learning all the concepts involved is a daunting task, each project is preceded by a "building blocks" section, where individual concepts are explored individually. These building blocks will consist of external readings, external programming problems, and other single-subject content. The building blocks sections are an opportunity to clear your mind, step away from the larger project, and focus your attention on learning and practicing a single subject in isolation. **Do not pass them up**. Each project builds on the last — the APIs, command-line interfaces, and parts of the implementation will often remain the same between projects, while you only integrate new features and improvements related to a project's subject matter. As such, it is ok to begin each project by copying your source code from the last. The projects live in the [`projects` subdirectory][psd], each in their own directories, and consist of a project description in `README.md`, and a Cargo project containing a complete example solution, and the project test suite. Each project comes with a test suite, and the project should not be considered finished until it passes with `cargo test`. **You should not read the example code for any project until completing the project yourself** — good learning requires trying on your own and failing, over and over until you succeed. You are encouraged though to learn from and apply techniques they contain to your own projects retroactively. Keep in mind though that the example projects are not the only way — or even the best way — to solve the problems. Trust yourself and your own creativity. You will receive further instruction about setting up the source code and test suite, as well as project specifications, as you progress through the individual projects. The expected time to complete each section is not currently well-estimated, but both "building blocks" and "project" will probably take hours, not days, with the projects taking more time. If you are spending much less time than that, or are spending more time, don't worry: these are just bad estimates, and everybody's experience is different. ## Getting help You will run into problems that you don't know how to solve. Don't suffer in silence. Everybody needs help sometimes. And fortunately the Rust community is amazing and welcoming, and wants to help you. As you are progressing through this course, you are _strongly_ encouraged to join the Rust community experience. Here are the resources you should consider turning to first: - The #rust-training channel on the [TiKV Slack]. This channel exists just for this course. Please consider joining to support your fellow students and other course-takers. There will always be someone there to answer questions, but there may be a delay due to time zones and other factors. Both English and Chinese languages are welcome here. - The `#beginners` channel on the official [Rust Discord]. You are almost guaranteed to get some answer here, and if not, don't hesitate to ask again. The people who hang out here are there specifically to help. Because of time zone differences it may take time for somebody to respond. Only English will be consistently understood here. - The QQ Rust group #1 ([QR code][qq]). For Chinese students, this is one of the major Rust communities in China. This is a great place to hang out generally, and for those unconfident in their English skills, a great place to ask for help. There are also WeChat groups, but with their low population caps and invite requirements, they are more difficult to deal with here. - The QQ Rust group #2 ([QR code][qq2]). Like the above. If group 1 is at capacity you can get into this one. These resources may also be helpful: - The official [users forum]. Apply the "help" tag to your post. Questions usually receive an answer here, but the responses can be limited. - [StackOverflow]. Apply the "rust" tag. You may or may not receive a satisfying answer. You are also welcome to email the primary author of this course, [Brian Anderson][brson], at brian@pingcap.com. I will happily answer questions, and am eager to hear your experience with the course. Finally, if there is a [Rust meetup] near you, go check it out. As a Rust programmer these groups are where you will build some of your strongest connections. (Note that that link goes to the old Rust website and may not be up to date). ## Making PNA Rust better As you work through the course content, please be on the lookout for things you would improve about the course, and either [submit issues][si] explaining, or [submit pull requests][spr] with improvements. (If you are being graded, accepted pull requests to this or any other repo used in the course _may_ count toward extra credit during final evaluation — let your instructor or evaluator know!). This is an opportunity to gain experience contributing to an open-source Rust project. Make this a better course for the next person to take it than it was for you. See [CONTRIBUTING.md] for more. ## Practical Networked Applications in Rust This is an outline of the course. Clicking each header will take you to the instructions for that section. ### [Building Blocks 1][b1] **Topics**: CLI programming, the cargo manifest and environment variables, documenting Rust projects. ### [Project 1: The Rust toolbox][p1] **Task**: Create an in-memory key/value store that passes simple tests and responds to command-line arguments. **Goals**: - Install the Rust compiler and tools - Learn the project structure used throughout this course - Use `cargo init` / `run` / `test` / `clippy` / `fmt` - Learn how to find and import crates from crates.io - Define an appropriate data type for a key-value store **Topics**: testing, the `clap` crate, `CARGO_VERSION` etc., the `clippy` and `rustfmt` tools. **Extensions**: the `structopt` crate. ### [Building Blocks 2][b2] **Topics**: log-structured file I/O, the bitcask algorithm, Rust error handling, comparing collection types. ### [Project 2: Log-structured file I/O][p2] **Task**: Create a persistent key/value store that can be accessed from the command line. **Goals**: - Handle and report errors robustly - Use serde for serialization - Write data to disk as a log using standard file APIs - Read the state of the key/value store from disk - Map in-memory key-indexes to on-disk values - Periodically compact the log to remove stale data **Topics**: log-structured file I/O, bitcask, the `failure` crate, `Read` / `Write` traits, the `serde` crate. ### [Building Blocks 3][b3] **Topics**: unstructured vs. structured logging, the Redis protocol, benchmarking. ### [Project 3: Synchronous client-server networking][p3] **Task**: Create a single-threaded, persistent key/value store server and client with synchronous networking over a custom protocol. **Goals**: - Create a client-server application - Write a custom protocol with `std` networking APIs - Introduce logging to the server - Implement pluggable backends with traits - Benchmark the hand-written backend against `sled` **Topics**: `std::net`, logging, traits, benchmarking. ### [Building Blocks 4][b4] **Topics**: multithreading, thread pools, aliasing and mutability, concurrent data types. ### [Project 4: Concurrency and parallelism][p4] **Task**: Create a multithreaded, persistent key/value store server and client with synchronous networking over a custom protocol. **Goals**: - Write a simple thread pool - Use channels for cross-thread communication - Share data structures with locks - Perform read operations without locks - Benchmark single-threaded vs multithreaded **Topics**: thread pools, channels, locks, lock-free data structures, atomics, parameterized benchmarking. ### Building Blocks 5 Coming soon! ([preview][b5]) ### Project 5: Asynchronous programming in Rust Coming soon! ([preview][p5]) ## What next? So you have completed Practical Networked Applications in Rust. That's a Rusty accomplishment! Now you are on the path to being a great Rust programmer. Want to know where to go next on that path? We've got [some ideas][n]. [b1]: ../building-blocks/bb-1.md [b2]: ../building-blocks/bb-2.md [b3]: ../building-blocks/bb-3.md [b4]: ../building-blocks/bb-4.md [b5]: ../building-blocks/bb-5.md [p1]: ../projects/project-1/README.md [p2]: ../projects/project-2/README.md [p3]: ../projects/project-3/README.md [p4]: ../projects/project-4/README.md [p5]: ../projects/project-5/README.md [CONTRIBUTING.md]: ../CONTRIBUTING.md [README.md]: ../README.md [Rust Discord]: https://discord.gg/rust-lang [Rust meetup]: https://www.meetup.com/topics/rust [StackOverflow]: https://stackoverflow.com/questions/tagged/rust [TiKV Slack]: https://join.slack.com/t/tikv-wg/shared_invite/enQtNTUyODE4ODU2MzI0LWVlMWMzMDkyNWE5ZjY1ODAzMWUwZGVhNGNhYTc3MzJhYWE0Y2FjYjliYzY1OWJlYTc4OWVjZWM1NDkwN2QxNDE [author]: https://github.com/brson/ [brson]: https://github.com/brson/ [kv]: https://en.wikipedia.org/wiki/Key-value_database [pre]: ../README.md#user-content-prerequisites [psd]: https://github.com/pingcap/talent-plan/tree/master/courses/rust/projects [qq]: ./qq-qr.jpg [qq2]: ./qq2-qr.jpg [rs]: https://github.com/pingcap/talent-plan/tree/master/courses/rust [si]: https://github.com/pingcap/talent-plan/issues [spr]: https://github.com/pingcap/talent-plan/pulls [users forum]: https://users.rust-lang.org/ [n]: ./what-next.md ================================================ FILE: courses/rust/docs/prerequisites.md ================================================ # PNA Rust Prerequisites Don't meet all the [prerequisites][pre] to take this course? Here are some ideas for how to proceed. * A crash course on Rust by Michael Snoyman (Oct 2018) - [blog series][snoyman-blog] | [print friendly][snoyman-html] [pre]: ../README.md#user-content-prerequisites [snoyman-blog]: https://www.snoyman.com/blog/2018/10/introducing-rust-crash-course [snoyman-html]: https://www.snoyman.com/series/rust-crash-course ================================================ FILE: courses/rust/docs/roadmap.md ================================================ # PNA Rust Roadmap We've got a lot of ideas about how to extend and expand this course. But the roadmap isn't written yet. In the meantime, [notes.md] contains a bunch of unorganized thoughts about the matter. [notes.md]: ./etc/notes.md ================================================ FILE: courses/rust/docs/what-next.md ================================================ # What's next now that you've completed PNA Rust? Coming soon! ================================================ FILE: courses/rust/projects/project-1/Cargo.toml ================================================ [package] name = "kvs" version = "0.1.0" authors = ["Yilin Chen "] description = "A key-value store" edition = "2018" [dependencies] clap = "2.32.0" [dev-dependencies] assert_cmd = "0.11.0" predicates = "1.0.0" ================================================ FILE: courses/rust/projects/project-1/README.md ================================================ # PNA Rust Project 1: The Rust toolbox **Task**: Create an in-memory key/value store that passes simple tests and responds to command-line arguments. **Goals**: - Install the Rust compiler and tools - Learn the project structure used throughout this course - Use `cargo init` / `run` / `test` / `clippy` / `fmt` - Learn how to find and import crates from crates.io - Define an appropriate data type for a key-value store **Topics**: testing, the `clap` crate, `CARGO_VERSION` etc., the `clippy` and `rustfmt` tools. **Extensions**: the `structopt` crate. - [Introduction](#user-content-introduction) - [Project spec](#user-content-project-spec) - [Installation](#user-content-installation) - [Project setup](#user-content-project-setup) - [Part 1: Make the tests compile](#user-content-part-1-make-the-tests-compile) - [Aside: Testing tips](#user-content-aside-testing-tips) - [Part 2: Accept command line arguments](#user-content-part-2-accept-command-line-arguments) - [Part 3: Cargo environment variables](#user-content-part-3-cargo-environment-variables) - [Part 4: Store values in memory](#user-content-part-4-store-values-in-memory) - [Part 5: Documentation](#user-content-part-5-documentation) - [Part 6: Ensure good style with `clippy` and `rustfmt`](#user-content-part-6-ensure-good-style-with-clippy-and-rustfmt) - [Extension 1: `structopt`](#user-content-extension-1-structopt) ## Introduction In this project you will create a simple in-memory key/value store that maps strings to strings, and that passes some tests and responds to command line arguments. The focus of this project is on the tooling and setup that goes into a typical Rust project. If this sounds basic to you, please do the project anyway as it discusses some general patterns that will be used throughout the course. ## Project spec The cargo project, `kvs`, builds a command-line key-value store client called `kvs`, which in turn calls into a library called `kvs`. The `kvs` executable supports the following command line arguments: - `kvs set ` Set the value of a string key to a string - `kvs get ` Get the string value of a given string key - `kvs rm ` Remove a given key - `kvs -V` Print the version The `kvs` library contains a type, `KvStore`, that supports the following methods: - `KvStore::set(&mut self, key: String, value: String)` Set the value of a string key to a string - `KvStore::get(&self, key: String) -> Option` Get the string value of the a string key. If the key does not exist, return `None`. - `KvStore::remove(&mut self, key: String)` Remove a given key. The `KvStore` type stores values in-memory, and thus the command-line client can do little more than print the version. The `get`/ `set` / `rm` commands will return an "unimplemented" error when run from the command line. Future projects will store values on disk and have a working command line interface. ## Installation At this point in your Rust programming experience you should know how to install Rust via [rustup]. [rustup]: https://www.rustup.rs If you haven't already, do so now by running ``` curl https://sh.rustup.rs -sSf | sh ``` (If you are running Windows then follow the instructions on rustup.rs. Note though that you will face more challenges than others during this course, as it was developed on Unix. In general, Rust development on Windows is a less polished experience than on Unix). Verify that the toolchain works by typing `rustc -V`. If that doesn't work, log out and log in again so that changes to the login profile made during installation can take effect. ## Project setup You will do the work for this project in your own git repository, with your own Cargo project. You will import the test cases for the project from the [source repository for this course][course]. [course]: https://github.com/pingcap/talent-plan Note that within that repository, all content related to this course is within the `rust` subdirectory. You may ignore any other directories. The projects in this course contain both libraries and executables. They are executables because we are developing an application that can be run. They are libraries because the supplied test cases must link to them. We'll use the same setup for each project in this course. The directory layout we will use is: ``` ├── Cargo.toml ├── src │   ├── bin │   │   └── kvs.rs │   └── lib.rs └── tests └── tests.rs ``` The `Cargo.toml`, `lib.rs` and `kvs.rs` files look as follows: `Cargo.toml`: ```toml [package] name = "kvs" version = "0.1.0" authors = ["Brian Anderson "] description = "A key-value store" edition = "2018" ``` `lib.rs`: ```rust // just leave it empty for now ``` `kvs.rs`: ```rust fn main() { println!("Hello, world!"); } ``` The author should be yourself, but the name needs to be `kvs` in order for the test cases to work. That's because the project name is also the name of the library it contains. Likewise the name of the binary (the command line application) needs to be `kvs`. In the above setup it will be `kvs` implicitly based on the file name, but you could name the file whatever you wanted by putting the appropriate information in the manifest (`Cargo.toml`). You may set up this project with `cargo new --lib`, `cargo init --lib` (in a clean directory), or manually. You'll probably also want to initialize a git repository in the same directory. Finally, the `tests` directory is copied from the course materials. In this case, copy from the course repository the file `rust/projects/project-1/tests` into your own repository, as `tests`. At this point you should be able to run the program with `cargo run`. _Try it now._ You are set up for this project and ready to start hacking. ## Part 1: Make the tests compile You've been provided with a suite of unit tests in `tests/tests.rs`. Open it up and take a look. _Try to run the tests with `cargo test`._ What happens? Why? Your first task for this project is to make the tests _compile_. Fun! If your project is like mine you probably saw a huge spew of build errors. Look at the first few. In general, when you see a bunch of errors, the first are the most important — `rustc` will keep trying to compile even after hitting errors, so errors can cascade, the later ones being pretty meaningless. Your first few errors probably look like: ``` error[E0433]: failed to resolve: use of undeclared type or module `assert_cmd` --> tests/tests.rs:1:5 | 1 | use assert_cmd::prelude::*; | ^^^^^^^^^^ use of undeclared type or module `assert_cmd` error[E0432]: unresolved import --> tests/tests.rs:3:5 | 3 | use predicates::str::contains; | ^^^^^^^^^^^^^^^^^^^^^^^^^ ``` (If you are seeing something else, please file an issue). These two errors are quite hard to diagnose to a new Rust programmer so I'll just tell you what's going on here: you are missing [dev-dependency] crates in your manifest. [dev-dependency]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#development-dependencies For this project your `Cargo.toml` file needs to contain these lines: ```toml [dev-dependencies] assert_cmd = "0.11.0" predicates = "1.0.0" ``` The details of these dependencies are not important to you completing the project, but you might want to investigate them on your own. We didn't tell you about the need for dev-deps earlier just so you would experience these errors yourself. In future projects, the setup text will tell you the dev-deps you need. One quick note: how can you figure out that these errors are due to missing dependencies in your manifest and not due to errors in your source code? Here's one big clue, from the error shown previously: ``` 1 | use assert_cmd::prelude::*; | ^^^^^^^^^^ use of undeclared type or module `assert_cmd` ``` In `use` statements the first path element is always the name of a crate. The exception to this is when the first path element references a name that was previously brought into scope with _another_ `use` statement. In other words, if there had been another `use` statement in this file like `use foo::assert_cmd`, then use `assert_cmd::prelude::*` would refer to _that_ `assert_cmd`. There is more that could be said about this but we shouldn't go deeper into the nuances of path resolution here. Just know that, in general, in a `use` statement, if the first element in the path isn't found (i.e. cannot be resolved), the problem is probably that the crate hasn't been named in the manifest. Whew. That is an unfortunate diversion in the very first project. But hopefully instructive. _Go ahead and add the appropriate dev-deps to your manifest._ Try again to run the tests with `cargo test`. What happens? Why? Hopefully those _previous_ errors are gone. Now the errors are all about the test cases not being able to find all the code it expects in your own code. _So now your task is to outline all the types, methods, etc. necessary to make the tests build._ During this course you will read the test cases a lot. The test cases tell you exactly what is expected of your code. If the text and the tests don't agree, the tests are right (file a bug!). This is true in the real world too. The test cases demonstrate what the software _actually_ does. They are reality. Get used to reading test cases. And, bonus — test cases are often the poorest-written code in any project, sloppy and undocumented. Again, try to run the tests with `cargo test`. What happens? Why? In `src/lib.rs` write the type and method definitions necessary to make `cargo test --no-run` complete successfully. Don't write any method bodies yet — instead write `panic!()`. This is the way to sketch out your APIs without knowing or caring about the implementation (there's also the [`unimplemented!`] macro, but since typing it is longer, it's common to simply use `panic!`, a possible exception being if you are releasing software that contains unimplemented methods). [`unimplemented!`]: https://doc.rust-lang.org/std/macro.unimplemented.html _Do that now before moving on._ Once that is done, if you run `cargo test` (without `--no-run`), you should see that some of your tests are failing, like ``` Finished dev [unoptimized + debuginfo] target(s) in 2.32s Running target/debug/deps/kvs-b03a01e7008067f6 running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Running target/debug/deps/kvs-a3b5a004932c6715 running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Running target/debug/deps/tests-5e1c2e20bd1fa377 running 13 tests test cli_get ... FAILED test cli_invalid_get ... FAILED test cli_invalid_rm ... FAILED test cli_invalid_set ... FAILED test cli_no_args ... FAILED test cli_invalid_subcommand ... FAILED ... more lines of spew ... ``` ... followed by many more lines. That's great! That's all we need right now. You'll make those pass throughout the rest of this project. ### Aside: Testing tips If you look again at the output from `cargo test` you'll see something interesting: ``` Running target/debug/deps/kvs-b03a01e7008067f6 running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Running target/debug/deps/kvs-a3b5a004932c6715 running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Running target/debug/deps/tests-5e1c2e20bd1fa377 running 13 tests test cli_get ... FAILED ``` Cargo says "Running ..." three times. And the first two of those times it in fact did not run any tests. And furthermore, if all those tests hadn't failed, cargo would have run _yet another_ set of tests. Why is this? Well, it is because there are many places you can write tests in Rust: - Inside the source of your library - Inside the source of each of your binaries - Inside each test file - In the doc comments of your library And cargo doesn't know which of these actually contain tests, so it just builds and runs them all. So those two sets of empty tests: ``` Running target/debug/deps/kvs-b03a01e7008067f6 running 0 tests Running target/debug/deps/kvs-a3b5a004932c6715 running 0 tests ``` Well, this is a bit confusing, but one of them is your library, compiled for testing, and the other is your binary, compiled for testing. Neither contains any tests. The reason both have "kvs" in their names is because both your library and your binary are called "kvs". All this test spew gets annoying, and there are two ways to quiet cargo: with command line arguments, and with changes to the manifest. Here are the relevant command line flags: - `cargo test --lib` — test just the tests inside the library - `cargo test --doc` — test the doc tests in the library - `cargo test --bins` — test all the bins in the project - `cargo test --bin foo` — test just the `foo` bin - `cargo test --test foo` — test the tests in test file `foo` These are convenient to quickly hide test spew, but if a project doesn't contain a type of tests it's probably best to just never deal with them. If you recall from The Cargo Book's [manifest description][m], there are two keys that can be applied: `test = false` and `doctest = false`. They go in the `[lib]` and `[[bin]]` sections. Consider updating your manifest. [m]: https://doc.rust-lang.org/cargo/reference/manifest.html Another quick thing to do if you haven't before. Run this: ``` cargo test -- --help ``` Just do it. It's cool. What you are seeing there is the help information for _the executable containing your compiled tests_ (that `--` surrounded by spaces tells cargo to pass all following arguments to the test binary). It's not the same info displayed when you run `cargo test --help`. They are two different things: cargo is running your test bin by passing it all these various arguments. If you want you can do exactly the same thing. Let's go back one more time to our `cargo test` example. We saw this line: ``` Running target/debug/deps/kvs-b03a01e7008067f6 ``` That's cargo telling you the name of the test binary. You can run it yourself, like `target/debug/deps/kvs-b03a01e7008067f6 --help`. The `target` directory contains lots of cool stuff. Digging through it can teach you a lot about what the Rust toolchain is actually doing. In practice, particularly with large projects, you won't run the entire test suite while developing a single feature. To narrow down the set of tests to the ones we care about, run the following: ``` cargo test cli_no_args ``` This will run the test called `cli_no_args`. In fact, it will run any test containing `cli_no_args` in the name, so if, e.g., you want to run all the CLI tests, you can run `cargo test cli`. That's probably how you will be running the tests yourself as you work through the project, otherwise you will be distracted by the many failing tests that you have not yet fixed. Unfortunately that pattern is a simple substring match, not something fancy like a regular expression. Note that, as of this writing, the test cases for the projects in this course are not organized in a way that makes it clear which test cases should complete for any particular section of a project — only that by the end the entire suite should pass. You'll need to read the names and implementations of the tests to figure out which you _think_ should pass at any particular time. ## Part 2: Accept command line arguments The key / value stores throughout this course are all controlled through a command-line client. In this project the command-line client is very simple because the state of the key-value store is only stored in memory, not persisted to disk. In this part you will make the `cli_*` test cases pass. Recall how to run individual test cases from previous sections of Again, the interface for the CLI is: - `kvs set ` Set the value of a string key to a string - `kvs get ` Get the string value of a given string key - `kvs rm ` Remove a given key - `kvs -V` Print the version In this iteration though, the `get` and `set` commands will print to stderr the string, "unimplemented", and exiting with a non-zero exit code, indicating an error. You will use the `clap` crate to handle command-line arguments. _Find the latest version of the `clap` crate and add it to your dependencies in `Cargo.toml`._ There are a number of ways to find and import a crate, but pro-tip: check out the built-in [`cargo search`] and the plug-in [`cargo edit`]. [`cargo search`]: https://doc.rust-lang.org/cargo/commands/cargo-search.html [`cargo edit`]: https://github.com/killercup/cargo-edit Next use [crates.io], [lib.rs], or [docs.rs] to find the documentation for the `clap` crate, and implement the command line interface such that the `cli_*` test cases pass. When you are testing, use `cargo run`; do not run the executable directly from the `target/` directory. When passing arguments to the program, separate them from the `cargo run` command with two dashes, `--`, like `cargo run -- get key1`. [crates.io]: https://crates.io [lib.rs]: https://lib.rs [docs.rs]: https://docs.rs ## Part 3: Cargo environment variables When you set up `clap` to parse your command line arguments, you probably set the name, version, authors, and description (if not, do so). This information is redundant w/ values provided in `Cargo.toml`. Cargo sets environment variables that can be accessed through Rust source code, at build time. _Modify your `clap` setup to set these values from standard cargo environment variables._ ## Part 4: Store values in memory Now that your command line scaffolding is done, let's turn to the implementation of `KvStore`, and make the remaining test cases pass. The behavior of `KvStore`'s methods are fully-defined through the test cases themselves — you don't need any further description to complete the code for this project. _Make the remaining test cases pass by implementing methods on `KvStore`._ ## Part 5: Documentation You have implemented the project's functionality, but there are still a few more things to do before it is a polished piece of Rust software, ready for contributions or publication. First, public items should generally have doc comments. Doc comments are displayed in a crate's API documentation. API documentation can be generated with the command, `cargo doc`, which will render them as HTML to the `target/doc` folder. Note though that `target/doc` folder does not contain an `index.html`. In this project, your crate's documentation will be located at `target/doc/kvs/index.html`. You can launch a web browser at that location with `cargo doc --open`. `cargo doc --open` doesn't always work, e.g. if you are ssh'd into a cloud instance. If it doesn't though the command will print the name of the html file it couldn't open — useful simply for finding the location of your API docs. [Good doc comments][gdc] do not just repeat the name of the function, nor repeat information gathered from the type signature. They explain why and how one would use a function, what the return value is on both success and failure, error and panic conditions. The library you have written is very simple so the documentation can be simple as well. If you truly cannot think of anything useful to add through doc comments then it can be ok to not add a doc comment (this is a matter of preference). With no doc comments it should be obvious how the type or function is used from the name and type signature alone. Doc comments contain examples, and those examples can be tested with `cargo test --doc`. _Add `#![deny(missing_docs)]` to the top of `src/lib.rs` to enforce that all public items have doc comments. Then add doc comments to the types and methods in your library. Follow the [documentation guidelines][gdc]. Give each an example and make sure they pass `cargo test --doc`._ [gdc]: https://rust-lang-nursery.github.io/api-guidelines/documentation.html ## Part 6: Ensure good style with `clippy` and `rustfmt` [`clippy`] and [`rustfmt`] are tools for enforcing common Rust style. `clippy` helps ensure that code uses modern idioms, and prevents patterns that commonly lead to errors. `rustfmt` enforces that code is formatted consistently. It's not necessary right now, but you might click those links and read their documentation. They are both sophisticated tools capable of much more than described below. [`clippy`]: https://github.com/rust-lang/rust-clippy [`rustfmt`]: https://github.com/rust-lang/rustfmt Both tools are included in the Rust toolchain, but not installed by default. They can be installed with the following [`rustup`] commands: ``` rustup component add clippy rustup component add rustfmt ``` [`rustup`]: https://github.com/rust-lang/rustup.rs/blob/master/README.md _Do that now._ Both tools are invoked as cargo subcommands, `clippy` as `cargo clippy` and `rustfmt` as `cargo fmt`. Note that `cargo fmt` modifies your source code, so commit your work before making before running it to avoid accidentally making unwanted changes, after which you can either include the changes as part of the previous commit with `git commit --amend`. Or just commit them as their own formatting commit — it's common to rust both `clippy` and `rustfmt` after a series of commits, e.g. before submitting a pull request. _Run `cargo clippy` against your project and make any suggested changes. Run `cargo fmt` against your project and commit any changes it makes._ It's worth reading the [`rustup`], [`clippy`], and [`rustfmt`] documentation, as these are tools you will be using frequently. Congratulations, you are done with your first project! If you like you may complete the remaining "extensions". They are optional. Nice coding, friend. Enjoy a nice break. --- ## Extension 1: `structopt` In this project we used `clap` to parse command line arguments. It's typical to represent a program's parsed command line arguments as a struct, perhaps named `Config` or `Options`. Doing so requires calling the appropriate methods on `clap`'s `ArgMatches` type. Both steps, for larger programs, require _a lot_ of boilerplate code. The `structopt` crate greatly reduces boilerplate by allowing you to define a `Config` struct, annotated to automatically produce a `clap` command line parser that produces that struct. Some find this approach nicer than writing the `clap` code explicitly. _Modify your program to use `structopt` for parsing command line arguments instead of using `clap` directly._ ================================================ FILE: courses/rust/projects/project-1/src/bin/kvs.rs ================================================ use clap::{App, AppSettings, Arg, SubCommand}; use std::process::exit; fn main() { let matches = App::new(env!("CARGO_PKG_NAME")) .version(env!("CARGO_PKG_VERSION")) .author(env!("CARGO_PKG_AUTHORS")) .about(env!("CARGO_PKG_DESCRIPTION")) .setting(AppSettings::DisableHelpSubcommand) .setting(AppSettings::SubcommandRequiredElseHelp) .setting(AppSettings::VersionlessSubcommands) .subcommand( SubCommand::with_name("set") .about("Set the value of a string key to a string") .arg(Arg::with_name("KEY").help("A string key").required(true)) .arg( Arg::with_name("VALUE") .help("The string value of the key") .required(true), ), ) .subcommand( SubCommand::with_name("get") .about("Get the string value of a given string key") .arg(Arg::with_name("KEY").help("A string key").required(true)), ) .subcommand( SubCommand::with_name("rm") .about("Remove a given key") .arg(Arg::with_name("KEY").help("A string key").required(true)), ) .get_matches(); match matches.subcommand() { ("set", Some(_matches)) => { eprintln!("unimplemented"); exit(1); } ("get", Some(_matches)) => { eprintln!("unimplemented"); exit(1); } ("rm", Some(_matches)) => { eprintln!("unimplemented"); exit(1); } _ => unreachable!(), } } ================================================ FILE: courses/rust/projects/project-1/src/kv.rs ================================================ use std::collections::HashMap; /// The `KvStore` stores string key/value pairs. /// /// Key/value pairs are stored in a `HashMap` in memory and not persisted to disk. /// /// Example: /// /// ```rust /// # use kvs::KvStore; /// let mut store = KvStore::new(); /// store.set("key".to_owned(), "value".to_owned()); /// let val = store.get("key".to_owned()); /// assert_eq!(val, Some("value".to_owned())); /// ``` #[derive(Default)] pub struct KvStore { map: HashMap, } impl KvStore { /// Creates a `KvStore`. pub fn new() -> KvStore { KvStore { map: HashMap::new(), } } /// Sets the value of a string key to a string. /// /// If the key already exists, the previous value will be overwritten. pub fn set(&mut self, key: String, value: String) { self.map.insert(key, value); } /// Gets the string value of a given string key. /// /// Returns `None` if the given key does not exist. pub fn get(&self, key: String) -> Option { self.map.get(&key).cloned() } /// Remove a given key. pub fn remove(&mut self, key: String) { self.map.remove(&key); } } ================================================ FILE: courses/rust/projects/project-1/src/lib.rs ================================================ #![deny(missing_docs)] //! A simple key/value store. pub use kv::KvStore; mod kv; ================================================ FILE: courses/rust/projects/project-1/tests/tests.rs ================================================ use assert_cmd::prelude::*; use kvs::KvStore; use predicates::str::contains; use std::process::Command; // `kvs` with no args should exit with a non-zero code. #[test] fn cli_no_args() { Command::cargo_bin("kvs").unwrap().assert().failure(); } // `kvs -V` should print the version #[test] fn cli_version() { Command::cargo_bin("kvs") .unwrap() .args(&["-V"]) .assert() .stdout(contains(env!("CARGO_PKG_VERSION"))); } // `kvs get ` should print "unimplemented" to stderr and exit with non-zero code #[test] fn cli_get() { Command::cargo_bin("kvs") .unwrap() .args(&["get", "key1"]) .assert() .failure() .stderr(contains("unimplemented")); } // `kvs set ` should print "unimplemented" to stderr and exit with non-zero code #[test] fn cli_set() { Command::cargo_bin("kvs") .unwrap() .args(&["set", "key1", "value1"]) .assert() .failure() .stderr(contains("unimplemented")); } // `kvs rm ` should print "unimplemented" to stderr and exit with non-zero code #[test] fn cli_rm() { Command::cargo_bin("kvs") .unwrap() .args(&["rm", "key1"]) .assert() .failure() .stderr(contains("unimplemented")); } #[test] fn cli_invalid_get() { Command::cargo_bin("kvs") .unwrap() .args(&["get"]) .assert() .failure(); Command::cargo_bin("kvs") .unwrap() .args(&["get", "extra", "field"]) .assert() .failure(); } #[test] fn cli_invalid_set() { Command::cargo_bin("kvs") .unwrap() .args(&["set"]) .assert() .failure(); Command::cargo_bin("kvs") .unwrap() .args(&["set", "missing_field"]) .assert() .failure(); Command::cargo_bin("kvs") .unwrap() .args(&["set", "extra", "extra", "field"]) .assert() .failure(); } #[test] fn cli_invalid_rm() { Command::cargo_bin("kvs") .unwrap() .args(&["rm"]) .assert() .failure(); Command::cargo_bin("kvs") .unwrap() .args(&["rm", "extra", "field"]) .assert() .failure(); } #[test] fn cli_invalid_subcommand() { Command::cargo_bin("kvs") .unwrap() .args(&["unknown", "subcommand"]) .assert() .failure(); } // Should get previously stored value #[test] fn get_stored_value() { let mut store = KvStore::new(); store.set("key1".to_owned(), "value1".to_owned()); store.set("key2".to_owned(), "value2".to_owned()); assert_eq!(store.get("key1".to_owned()), Some("value1".to_owned())); assert_eq!(store.get("key2".to_owned()), Some("value2".to_owned())); } // Should overwrite existent value #[test] fn overwrite_value() { let mut store = KvStore::new(); store.set("key1".to_owned(), "value1".to_owned()); assert_eq!(store.get("key1".to_owned()), Some("value1".to_owned())); store.set("key1".to_owned(), "value2".to_owned()); assert_eq!(store.get("key1".to_owned()), Some("value2".to_owned())); } // Should get `None` when getting a non-existent key #[test] fn get_non_existent_value() { let mut store = KvStore::new(); store.set("key1".to_owned(), "value1".to_owned()); assert_eq!(store.get("key2".to_owned()), None); } #[test] fn remove_key() { let mut store = KvStore::new(); store.set("key1".to_owned(), "value1".to_owned()); store.remove("key1".to_owned()); assert_eq!(store.get("key1".to_owned()), None); } ================================================ FILE: courses/rust/projects/project-2/Cargo.toml ================================================ [package] name = "kvs" version = "0.1.0" authors = ["Yilin Chen "] description = "A key-value store" edition = "2018" [dependencies] clap = "2.32.0" failure = "0.1.5" serde = { version = "1.0.89", features = ["derive"] } serde_json = "1.0.39" [dev-dependencies] assert_cmd = "0.11.0" predicates = "1.0.0" tempfile = "3.0.7" walkdir = "2.2.7" ================================================ FILE: courses/rust/projects/project-2/README.md ================================================ # PNA Rust Project 2: Log-structured file I/O **Task**: Create a _persistent_ key/value store that _can be accessed from the command line_. **Goals**: - Handle and report errors robustly - Use serde for serialization - Write data to disk as a log using standard file APIs - Read the state of the key/value store from disk - Map in-memory key-indexes to on-disk values - Periodically compact the log to remove stale data **Topics**: log-structured file I/O, bitcask, the `failure` crate, `Read` / `Write` traits, the `serde` crate. - [Introduction](#user-content-introduction) - [Terminology](#user-content-terminology) - [Project spec](#user-content-project-spec) - [Project setup](#user-content-project-setup) - [Part 1: Error handling](#user-content-part-1-error-handling) - [Part 2: How the log behaves](#user-content-part-2-how-the-log-behaves) - [Part 3: Writing to the log](#user-content-part-3-writing-to-the-log) - [Part 4: Reading from the log](#user-content-part-4-reading-from-the-log) - [Part 5: Storing log pointers in the index](#user-content-part-5-storing-log-pointers-in-the-index) - [Part 6: Stateless vs. stateful `KvStore`](#user-content-part-6-stateless-vs-stateful-kvstore) - [Part 7: Compacting the log](#user-content-part-7-compacting-the-log) ## Introduction In this project you will create a simple on-disk key/value store that can be modified and queried from the command line. It will use a simplification of the storage algorithm used by [bitcask], chosen for its combination of simplicity and effectiveness. You will start by maintaining a _log_ (sometimes called a ["write-ahead log"][wal] or "WAL") on disk of previous write commands that is evaluated on startup to re-create the state of the database in memory. Then you will extend that by storing only the keys in memory, along with offsets into the on-disk log. Finally, you will introduce log compaction so that it does not grow indefinitely. At the end of this project you will have built a simple, but well-architected database using Rust file APIs. [wal]: https://en.wikipedia.org/wiki/Write-ahead_logging [bitcask]: https://github.com/basho/bitcask ## Terminology Some terminology we will use in this course. It is the same as or inspired by [bitcask]. Different databases will have slightly different terminology. - _command_ - A request or the representation of a request made to the database. These are issued on the command line or over the network. They have an in-memory representation, a textual representation, and a machine-readable serialized representation. - _log_ - An on-disk sequence of commands, in the order originally received and executed. Our database's on-disk format is almost entirely made up of logs. It will be simple, but also surprisingly efficient. - _log pointer_ - A file offset into the log. Sometimes we'll just call this a "file offset". - _log compaction_ - As writes are issued to the database they sometimes invalidate old log entries. For example, writing key/value `a = 0` then writing `a = 1`, makes the first log entry for "a" useless. Compaction — in our database at least — is the process of reducing the size of the database by remove stale commands from the log. - _in-memory index_ (or _index_) - A map of keys to log pointers. When a read request is issued, the in-memory index is searched for the appropriate log pointer, and when it is found the value is retrieved from the on-disk log. In our key/value store, like in bitcask, the index for the _entire database_ is stored in memory. - _index file_ - The on-disk representation of the in-memory index. Without this the log would need to be completely replayed to restore the state of the in-memory index each time the database is started. ## Project spec The cargo project, `kvs`, builds a command-line key-value store client called `kvs`, which in turn calls into a library called `kvs`. The `kvs` executable supports the following command line arguments: - `kvs set ` Set the value of a string key to a string. Print an error and return a non-zero exit code on failure. - `kvs get ` Get the string value of a given string key. Print an error and return a non-zero exit code on failure. - `kvs rm ` Remove a given key. Print an error and return a non-zero exit code on failure. - `kvs -V` Print the version The `kvs` library contains a type, `KvStore`, that supports the following methods: - `KvStore::set(&mut self, key: String, value: String) -> Result<()>` Set the value of a string key to a string. Return an error if the value is not written successfully. - `KvStore::get(&mut self, key: String) -> Result>` Get the string value of a string key. If the key does not exist, return `None`. Return an error if the value is not read successfully. - `KvStore::remove(&mut self, key: String) -> Result<()>` Remove a given key. Return an error if the key does not exist or is not removed successfully. - `KvStore::open(path: impl Into) -> Result` Open the KvStore at a given path. Return the KvStore. When setting a key to a value, `kvs` writes the `set` command to disk in a sequential log, then stores the log pointer (file offset) of that command in the in-memory index from key to pointer. When removing a key, similarly, `kvs` writes the `rm` command in the log, then removes the key from the in-memory index. When retrieving a value for a key with the `get` command, it searches the index, and if found then loads from the log the command at the corresponding log pointer, evaluates the command and returns the result. On startup, the commands in the log are traversed from oldest to newest, and the in-memory index rebuilt. When the size of the uncompacted log entries reach a given threshold, `kvs` compacts it into a new log, removing redundent entries to reclaim disk space. Note that our `kvs` project is both a stateless command-line program, and a library containing a stateful `KvStore` type: for CLI use the `KvStore` type will load the index, execute the command, then exit; for library use it will load the index, then execute multiple commands, maintaining the index state, until it is dropped. ## Project setup Continuing from your previous project, delete your previous `tests` directory and copy this project's `tests` directory into its place. Like the previous project, this project should contain a library and an executable, both named `kvs`. You need the following dev-dependencies in your `Cargo.toml`: ```toml [dev-dependencies] assert_cmd = "0.11.0" predicates = "1.0.0" tempfile = "3.0.7" walkdir = "2.2.7" ``` As with the previous project, go ahead and write enough empty or panicking definitions to make the test cases build. _Do that now._ ## Part 1: Error handling In this project it will be possible for the code to fail due to I/O errors. So before we get started implementing a database we need to do one more thing that is crucial to Rust projects: decide on an error handling strategy. Rust's error handling is powerful, but involves a lot of boilerplate to use correctly. For this project the [`failure`] crate will provide the tools to easily handle errors of all kinds. [`failure`]: https://docs.rs/failure/0.1.5/failure/ The [failure guide][fg] describes [several] error handling patterns. [fg]: https://boats.gitlab.io/failure/ [several]: https://boats.gitlab.io/failure/guidance.html Pick one of those strategies and, in your library, either define your own error type or import `failure`s `Error`. This is the error type you will use in all of your `Result`s, converting error types from other crates to your own with the `?` operator. After that, define a type alias for `Result` that includes your concrete error type, so that you don't need to type `Result` everywhere, but can simply type `Result`. This is a common Rust pattern. Finally, import those types into your executable with `use` statements, and change `main`s function signature to return `Result<()>`. All functions in your library that may fail will pass these `Results` back down the stack all the way to `main`, and then to the Rust runtime, which will print an error. Run `cargo check` to look for compiler errors, then fix them. For now it's ok to end `main` with `panic!()` to make the project build. _Set up your error handling strategy before continuing._ As with the previous project, you'll want to create placeholder data structures and methods so that the tests compile. Now that you have defined an error type this should be straightforward. Add panics anywhere necessary to get the test suite to compile (`cargo test --no-run`). _Note: Error-handling practices in Rust are still evolving. This course currently uses the [`failure`] crate to make defining error types easier. While `failure` has a good design, its use is [arguably not a best practice][nbp]. It may not continue to be viewed favorably by Rust experts. Future iterations of the course will likely not use `failure`. In the meantime, it is fine, and presents an opportunity to learn more of the history and nuance of Rust error handling._ [nbp]: https://github.com/rust-lang-nursery/rust-cookbook/issues/502#issue-387418261 ## Part 2: How the log behaves Now we are finally going to begin implementing the beginnings of a real database by reading and writing from disk. You will use [`serde`] to serialize the "set" and "rm" commands to a string, and the standard file I/O APIs to write it to disk. [`serde`]: https://serde.rs/ This is the basic behavior of `kvs` with a log: - "set" - The user invokes `kvs set mykey myvalue` - `kvs` creates a value representing the "set" command, containing its key and value - It then serializes that command to a `String` - It then appends the serialized command to a file containing the log - If that succeeds, it exits silently with error code 0 - If it fails, it exits by printing the error and returning a non-zero error code - "get" - The user invokes `kvs get mykey` - `kvs` reads the entire log, one command at a time, recording the affected key and file offset of the command to an in-memory _key -> log pointer_ map - It then checks the map for the log pointer - If it fails, it prints "Key not found", and exits with exit code 0 - If it succeeds - It deserializes the command to get the last recorded value of the key - It prints the value to stdout and exits with exit code 0 - "rm" - The user invokes `kvs rm mykey` - Same as the "get" command, `kvs` reads the entire log to build the in-memory index - It then checks the map if the given key exists - If the key does not exist, it prints "Key not found", and exits with a non-zero error code - If it succeeds - It creates a value representing the "rm" command, containing its key - It then appends the serialized command to the log - If that succeeds, it exits silently with error code 0 The log is a record of the transactions committed to the database. By "replaying" the records in the log on startup we reconstruct the previous state of the database. In this iteration you may store the value of the keys directly in memory (and thus never read from the log after initial startup and log replay). In a future iteration you will store only "log pointers" (file offsets) into the log. ## Part 3: Writing to the log You will start by implementing the "set" flow. There are a number of steps here. Most of them are straightforward to implement and you can verify you've done so by running the appropriate `cli_*` test cases. `serde` is a large library, with many options, and supporting many serialization formats. Basic serialization and deserialization only requires annotating your data structure correctly, and calling a function to write it either to a `String` or a stream implementing `Write`. You need to pick a serialization format. Think about the properties you want in your serialization format — do you want to prioritize performance? Do you want to be able to read the content of the log in plain text? It's your choice, but maybe you should include a comment in the code explaining it. Other things to consider include: where is the system performing buffering and where do you need buffering? What is the impact of buffering on subsequent reads? When should you open and close file handles? For each command? For the lifetime of the `KvStore`? Some of the APIs you will call may fail, and return a `Result` of some error type. Make sure that your calling functions return a `Result` of _your own_ error type, and that you convert between the two with `?`. It is similar to implementing the "rm" command, but you should additionally check if the key exists before writing the command to the log. As we have two different commands that must be distinguished, you may use variants of a single enum type to represent each command. `serde` just works perfectly with enums. You may implement the "set" and "rm" commands now, focusing on the `set` / `rm` test cases, or you can proceed to the next section to read about the "get" command. It may help to keep both in mind, or to implement them both simultaneously. It is your choice. ## Part 4: Reading from the log Now it's time to implement "get". In this part, you don't need to store log pointers in the index, we will leave the work to the next part. Instead, just read each command in the log on startup, executing them to save every key and value in the memory. Then read from the memory. Should you read all records in the log into memory at once and then replay them into your map type; or should you read them one at a time while replaying them into your map? Should you read into a buffer before deserializing or deserialize from a file stream? Think about the memory usage of your approach. Think about the way reading from I/O streams interacts with the kernel. Remember that "get" may not find a value and that case has to be handled specially. Here, our API returns `None` and our command line client prints a particular message and exits with a zero exit code. There's one complication to reading the log, and you may have already considered it while writing the "set" code: how do you distinguish between each record in the log? That is, how do you know when to stop reading one record, and start reading the next? Do you even need to? Maybe serde will deserialize a record directly from an I/O stream and stop reading when it's done, leaving the file cursor in the correct place to read subsequent records. Maybe serde will report an error when it sees two records back-to-back. Maybe you need to insert additional information to distinguish the length of each record. Maybe not. [`serde`]: https://serde.rs/ _Implement "get" now_. ## Part 5: Storing log pointers in the index At this point most, if not all (besides the compaction test), other test suite should all pass. The changes introduced in the next steps are simple optimizations, necessary for fast performance and reduced storage. As you implement them, pay attention to what exactly they are optimizing for. As we've described, the database you are building maintains an in-memory index of all keys in the database. That index maps from string keys to log pointers, not the values themselves. This change introduces the need to perform reads from the log at arbitrary offsets. Consider how that might impact the way you manage file handles. _If, in the previous steps, you elected to store the string values directly in memory, now is the time to update your code to store log pointers instead, loading from disk on demand._ ## Part 6: Stateless vs. stateful `KvStore` Remember that our project is both a library and a command-line program. They have sligtly different requirements: the `kvs` CLI commits a single change to disk, then exits (it is stateless); the `KvStore` type commits changes to disk, then stays resident in memory to service future queries (it is stateful). Is your `KvStore` stateful or stateless? _Make your `KvStore` retain the index in memory so it doesn't need to re-evaluate it for every call to `get`._ ## Part 7: Compacting the log At this point the database works just fine, but the log grows indefinitely. That is appropriate for some databases, but not the one we're building — we want to minimize disk usage as much as we can. So the final step in creating your database is to compact the log. Consider that as the log grows that multiple entries may set the value of a given key. Consider also that only the most recent command that modified a given key has any effect on the current value of that key: | idx | command | |:---:|:--------| | 0 | ~Command::Set("key-1", "value-1a")~ | | 20 | Command::Set("key-2", "value-2") | | | ... | | 100 | Command::Set("key-1", "value-1b") | In this example obviously the command at index 0 is redundant, so it doesn't need to be stored. Log compaction then is about rebuilding the log to remove redundancy: | idx | command | |:---:|:--------| | 0 | Command::Set("key-2", "value-2") | | | ... | | 99 | Command::Set("key-1", "value-1b") | Here's the basic algorithm you will use: _How_ you re-build the log is up to you. Consider questions like: what is the naive solution? How much memory do you need? What is the minimum amount of copying necessary to compact the log? Can the compaction be done in-place? How do you maintain data-integrity if compaction fails? So far we've been refering to "the log", but in actuallity it is common for a database to store many logs, in different files. You may find it easier to compact the log if you split your log across files. _Implement log compaction for your database._ Congratulations! You have written a fully-functional database. If you are curious, now is a good time to start comparing the performance of your key/value store to others, like [sled], [bitcask], [badger], or [RocksDB]. You might enjoy investigating their architectures, thinking about how theirs compare to yours, and how architecture affects performance. The next few projects will give you opportunities to optimize. [sled]: https://github.com/spacejam/sled [badger]: https://github.com/dgraph-io/badger [RocksDB]: https://rocksdb.org/ Nice coding, friend. Enjoy a nice break. ================================================ FILE: courses/rust/projects/project-2/src/bin/kvs.rs ================================================ use clap::{App, AppSettings, Arg, SubCommand}; use kvs::{KvStore, KvsError, Result}; use std::env::current_dir; use std::process::exit; fn main() -> Result<()> { let matches = App::new(env!("CARGO_PKG_NAME")) .version(env!("CARGO_PKG_VERSION")) .author(env!("CARGO_PKG_AUTHORS")) .about(env!("CARGO_PKG_DESCRIPTION")) .setting(AppSettings::DisableHelpSubcommand) .setting(AppSettings::SubcommandRequiredElseHelp) .setting(AppSettings::VersionlessSubcommands) .subcommand( SubCommand::with_name("set") .about("Set the value of a string key to a string") .arg(Arg::with_name("KEY").help("A string key").required(true)) .arg( Arg::with_name("VALUE") .help("The string value of the key") .required(true), ), ) .subcommand( SubCommand::with_name("get") .about("Get the string value of a given string key") .arg(Arg::with_name("KEY").help("A string key").required(true)), ) .subcommand( SubCommand::with_name("rm") .about("Remove a given key") .arg(Arg::with_name("KEY").help("A string key").required(true)), ) .get_matches(); match matches.subcommand() { ("set", Some(matches)) => { let key = matches.value_of("KEY").unwrap(); let value = matches.value_of("VALUE").unwrap(); let mut store = KvStore::open(current_dir()?)?; store.set(key.to_string(), value.to_string())?; } ("get", Some(matches)) => { let key = matches.value_of("KEY").unwrap(); let mut store = KvStore::open(current_dir()?)?; if let Some(value) = store.get(key.to_string())? { println!("{}", value); } else { println!("Key not found"); } } ("rm", Some(matches)) => { let key = matches.value_of("KEY").unwrap(); let mut store = KvStore::open(current_dir()?)?; match store.remove(key.to_string()) { Ok(()) => {} Err(KvsError::KeyNotFound) => { println!("Key not found"); exit(1); } Err(e) => return Err(e), } } _ => unreachable!(), } Ok(()) } ================================================ FILE: courses/rust/projects/project-2/src/error.rs ================================================ use failure::Fail; use std::io; /// Error type for kvs. #[derive(Fail, Debug)] pub enum KvsError { /// IO error. #[fail(display = "{}", _0)] Io(#[cause] io::Error), /// Serialization or deserialization error. #[fail(display = "{}", _0)] Serde(#[cause] serde_json::Error), /// Removing non-existent key error. #[fail(display = "Key not found")] KeyNotFound, /// Unexpected command type error. /// It indicated a corrupted log or a program bug. #[fail(display = "Unexpected command type")] UnexpectedCommandType, } impl From for KvsError { fn from(err: io::Error) -> KvsError { KvsError::Io(err) } } impl From for KvsError { fn from(err: serde_json::Error) -> KvsError { KvsError::Serde(err) } } /// Result type for kvs. pub type Result = std::result::Result; ================================================ FILE: courses/rust/projects/project-2/src/kv.rs ================================================ use std::collections::{BTreeMap, HashMap}; use std::fs::{self, File, OpenOptions}; use std::io::{self, BufReader, BufWriter, Read, Seek, SeekFrom, Write}; use std::ops::Range; use std::path::{Path, PathBuf}; use serde::{Deserialize, Serialize}; use serde_json::Deserializer; use crate::{KvsError, Result}; use std::ffi::OsStr; const COMPACTION_THRESHOLD: u64 = 1024 * 1024; /// The `KvStore` stores string key/value pairs. /// /// Key/value pairs are persisted to disk in log files. Log files are named after /// monotonically increasing generation numbers with a `log` extension name. /// A `BTreeMap` in memory stores the keys and the value locations for fast query. /// /// ```rust /// # use kvs::{KvStore, Result}; /// # fn try_main() -> Result<()> { /// use std::env::current_dir; /// let mut store = KvStore::open(current_dir()?)?; /// store.set("key".to_owned(), "value".to_owned())?; /// let val = store.get("key".to_owned())?; /// assert_eq!(val, Some("value".to_owned())); /// # Ok(()) /// # } /// ``` pub struct KvStore { // directory for the log and other data. path: PathBuf, // map generation number to the file reader. readers: HashMap>, // writer of the current log. writer: BufWriterWithPos, current_gen: u64, index: BTreeMap, // the number of bytes representing "stale" commands that could be // deleted during a compaction. uncompacted: u64, } impl KvStore { /// Opens a `KvStore` with the given path. /// /// This will create a new directory if the given one does not exist. /// /// # Errors /// /// It propagates I/O or deserialization errors during the log replay. pub fn open(path: impl Into) -> Result { let path = path.into(); fs::create_dir_all(&path)?; let mut readers = HashMap::new(); let mut index = BTreeMap::new(); let gen_list = sorted_gen_list(&path)?; let mut uncompacted = 0; for &gen in &gen_list { let mut reader = BufReaderWithPos::new(File::open(log_path(&path, gen))?)?; uncompacted += load(gen, &mut reader, &mut index)?; readers.insert(gen, reader); } let current_gen = gen_list.last().unwrap_or(&0) + 1; let writer = new_log_file(&path, current_gen, &mut readers)?; Ok(KvStore { path, readers, writer, current_gen, index, uncompacted, }) } /// Sets the value of a string key to a string. /// /// If the key already exists, the previous value will be overwritten. /// /// # Errors /// /// It propagates I/O or serialization errors during writing the log. pub fn set(&mut self, key: String, value: String) -> Result<()> { let cmd = Command::set(key, value); let pos = self.writer.pos; serde_json::to_writer(&mut self.writer, &cmd)?; self.writer.flush()?; if let Command::Set { key, .. } = cmd { if let Some(old_cmd) = self .index .insert(key, (self.current_gen, pos..self.writer.pos).into()) { self.uncompacted += old_cmd.len; } } if self.uncompacted > COMPACTION_THRESHOLD { self.compact()?; } Ok(()) } /// Gets the string value of a given string key. /// /// Returns `None` if the given key does not exist. /// /// # Errors /// /// It returns `KvsError::UnexpectedCommandType` if the given command type unexpected. pub fn get(&mut self, key: String) -> Result> { if let Some(cmd_pos) = self.index.get(&key) { let reader = self .readers .get_mut(&cmd_pos.gen) .expect("Cannot find log reader"); reader.seek(SeekFrom::Start(cmd_pos.pos))?; let cmd_reader = reader.take(cmd_pos.len); if let Command::Set { value, .. } = serde_json::from_reader(cmd_reader)? { Ok(Some(value)) } else { Err(KvsError::UnexpectedCommandType) } } else { Ok(None) } } /// Removes a given key. /// /// # Errors /// /// It returns `KvsError::KeyNotFound` if the given key is not found. /// /// It propagates I/O or serialization errors during writing the log. pub fn remove(&mut self, key: String) -> Result<()> { if self.index.contains_key(&key) { let cmd = Command::remove(key); serde_json::to_writer(&mut self.writer, &cmd)?; self.writer.flush()?; if let Command::Remove { key } = cmd { let old_cmd = self.index.remove(&key).expect("key not found"); self.uncompacted += old_cmd.len; } Ok(()) } else { Err(KvsError::KeyNotFound) } } /// Clears stale entries in the log. pub fn compact(&mut self) -> Result<()> { // increase current gen by 2. current_gen + 1 is for the compaction file. let compaction_gen = self.current_gen + 1; self.current_gen += 2; self.writer = self.new_log_file(self.current_gen)?; let mut compaction_writer = self.new_log_file(compaction_gen)?; let mut new_pos = 0; // pos in the new log file. for cmd_pos in &mut self.index.values_mut() { let reader = self .readers .get_mut(&cmd_pos.gen) .expect("Cannot find log reader"); if reader.pos != cmd_pos.pos { reader.seek(SeekFrom::Start(cmd_pos.pos))?; } let mut entry_reader = reader.take(cmd_pos.len); let len = io::copy(&mut entry_reader, &mut compaction_writer)?; *cmd_pos = (compaction_gen, new_pos..new_pos + len).into(); new_pos += len; } compaction_writer.flush()?; // remove stale log files. let stale_gens: Vec<_> = self .readers .keys() .filter(|&&gen| gen < compaction_gen) .cloned() .collect(); for stale_gen in stale_gens { self.readers.remove(&stale_gen); fs::remove_file(log_path(&self.path, stale_gen))?; } self.uncompacted = 0; Ok(()) } /// Create a new log file with given generation number and add the reader to the readers map. /// /// Returns the writer to the log. fn new_log_file(&mut self, gen: u64) -> Result> { new_log_file(&self.path, gen, &mut self.readers) } } /// Create a new log file with given generation number and add the reader to the readers map. /// /// Returns the writer to the log. fn new_log_file( path: &Path, gen: u64, readers: &mut HashMap>, ) -> Result> { let path = log_path(&path, gen); let writer = BufWriterWithPos::new( OpenOptions::new() .create(true) .write(true) .append(true) .open(&path)?, )?; readers.insert(gen, BufReaderWithPos::new(File::open(&path)?)?); Ok(writer) } /// Returns sorted generation numbers in the given directory. fn sorted_gen_list(path: &Path) -> Result> { let mut gen_list: Vec = fs::read_dir(&path)? .flat_map(|res| -> Result<_> { Ok(res?.path()) }) .filter(|path| path.is_file() && path.extension() == Some("log".as_ref())) .flat_map(|path| { path.file_name() .and_then(OsStr::to_str) .map(|s| s.trim_end_matches(".log")) .map(str::parse::) }) .flatten() .collect(); gen_list.sort_unstable(); Ok(gen_list) } /// Load the whole log file and store value locations in the index map. /// /// Returns how many bytes can be saved after a compaction. fn load( gen: u64, reader: &mut BufReaderWithPos, index: &mut BTreeMap, ) -> Result { // To make sure we read from the beginning of the file. let mut pos = reader.seek(SeekFrom::Start(0))?; let mut stream = Deserializer::from_reader(reader).into_iter::(); let mut uncompacted = 0; // number of bytes that can be saved after a compaction. while let Some(cmd) = stream.next() { let new_pos = stream.byte_offset() as u64; match cmd? { Command::Set { key, .. } => { if let Some(old_cmd) = index.insert(key, (gen, pos..new_pos).into()) { uncompacted += old_cmd.len; } } Command::Remove { key } => { if let Some(old_cmd) = index.remove(&key) { uncompacted += old_cmd.len; } // the "remove" command itself can be deleted in the next compaction. // so we add its length to `uncompacted`. uncompacted += new_pos - pos; } } pos = new_pos; } Ok(uncompacted) } fn log_path(dir: &Path, gen: u64) -> PathBuf { dir.join(format!("{}.log", gen)) } /// Struct representing a command. #[derive(Serialize, Deserialize, Debug)] enum Command { Set { key: String, value: String }, Remove { key: String }, } impl Command { fn set(key: String, value: String) -> Command { Command::Set { key, value } } fn remove(key: String) -> Command { Command::Remove { key } } } /// Represents the position and length of a json-serialized command in the log. struct CommandPos { gen: u64, pos: u64, len: u64, } impl From<(u64, Range)> for CommandPos { fn from((gen, range): (u64, Range)) -> Self { CommandPos { gen, pos: range.start, len: range.end - range.start, } } } struct BufReaderWithPos { reader: BufReader, pos: u64, } impl BufReaderWithPos { fn new(mut inner: R) -> Result { let pos = inner.seek(SeekFrom::Current(0))?; Ok(BufReaderWithPos { reader: BufReader::new(inner), pos, }) } } impl Read for BufReaderWithPos { fn read(&mut self, buf: &mut [u8]) -> io::Result { let len = self.reader.read(buf)?; self.pos += len as u64; Ok(len) } } impl Seek for BufReaderWithPos { fn seek(&mut self, pos: SeekFrom) -> io::Result { self.pos = self.reader.seek(pos)?; Ok(self.pos) } } struct BufWriterWithPos { writer: BufWriter, pos: u64, } impl BufWriterWithPos { fn new(mut inner: W) -> Result { let pos = inner.seek(SeekFrom::Current(0))?; Ok(BufWriterWithPos { writer: BufWriter::new(inner), pos, }) } } impl Write for BufWriterWithPos { fn write(&mut self, buf: &[u8]) -> io::Result { let len = self.writer.write(buf)?; self.pos += len as u64; Ok(len) } fn flush(&mut self) -> io::Result<()> { self.writer.flush() } } impl Seek for BufWriterWithPos { fn seek(&mut self, pos: SeekFrom) -> io::Result { self.pos = self.writer.seek(pos)?; Ok(self.pos) } } ================================================ FILE: courses/rust/projects/project-2/src/lib.rs ================================================ #![deny(missing_docs)] //! A simple key/value store. pub use error::{KvsError, Result}; pub use kv::KvStore; mod error; mod kv; ================================================ FILE: courses/rust/projects/project-2/tests/tests.rs ================================================ use assert_cmd::prelude::*; use kvs::{KvStore, Result}; use predicates::ord::eq; use predicates::str::{contains, is_empty, PredicateStrExt}; use std::process::Command; use tempfile::TempDir; use walkdir::WalkDir; // `kvs` with no args should exit with a non-zero code. #[test] fn cli_no_args() { Command::cargo_bin("kvs").unwrap().assert().failure(); } // `kvs -V` should print the version #[test] fn cli_version() { Command::cargo_bin("kvs") .unwrap() .args(&["-V"]) .assert() .stdout(contains(env!("CARGO_PKG_VERSION"))); } // `kvs get ` should print "Key not found" for a non-existent key and exit with zero. #[test] fn cli_get_non_existent_key() { let temp_dir = TempDir::new().unwrap(); Command::cargo_bin("kvs") .unwrap() .args(&["get", "key1"]) .current_dir(&temp_dir) .assert() .success() .stdout(eq("Key not found").trim()); } // `kvs rm ` should print "Key not found" for an empty database and exit with non-zero code. #[test] fn cli_rm_non_existent_key() { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); Command::cargo_bin("kvs") .unwrap() .args(&["rm", "key1"]) .current_dir(&temp_dir) .assert() .failure() .stdout(eq("Key not found").trim()); } // `kvs set ` should print nothing and exit with zero. #[test] fn cli_set() { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); Command::cargo_bin("kvs") .unwrap() .args(&["set", "key1", "value1"]) .current_dir(&temp_dir) .assert() .success() .stdout(is_empty()); } #[test] fn cli_get_stored() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let mut store = KvStore::open(temp_dir.path())?; store.set("key1".to_owned(), "value1".to_owned())?; store.set("key2".to_owned(), "value2".to_owned())?; drop(store); Command::cargo_bin("kvs") .unwrap() .args(&["get", "key1"]) .current_dir(&temp_dir) .assert() .success() .stdout(eq("value1").trim()); Command::cargo_bin("kvs") .unwrap() .args(&["get", "key2"]) .current_dir(&temp_dir) .assert() .success() .stdout(eq("value2").trim()); Ok(()) } // `kvs rm ` should print nothing and exit with zero. #[test] fn cli_rm_stored() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let mut store = KvStore::open(temp_dir.path())?; store.set("key1".to_owned(), "value1".to_owned())?; drop(store); Command::cargo_bin("kvs") .unwrap() .args(&["rm", "key1"]) .current_dir(&temp_dir) .assert() .success() .stdout(is_empty()); Command::cargo_bin("kvs") .unwrap() .args(&["get", "key1"]) .current_dir(&temp_dir) .assert() .success() .stdout(eq("Key not found").trim()); Ok(()) } #[test] fn cli_invalid_get() { Command::cargo_bin("kvs") .unwrap() .args(&["get"]) .assert() .failure(); Command::cargo_bin("kvs") .unwrap() .args(&["get", "extra", "field"]) .assert() .failure(); } #[test] fn cli_invalid_set() { Command::cargo_bin("kvs") .unwrap() .args(&["set"]) .assert() .failure(); Command::cargo_bin("kvs") .unwrap() .args(&["set", "missing_field"]) .assert() .failure(); Command::cargo_bin("kvs") .unwrap() .args(&["set", "extra", "extra", "field"]) .assert() .failure(); } #[test] fn cli_invalid_rm() { Command::cargo_bin("kvs") .unwrap() .args(&["rm"]) .assert() .failure(); Command::cargo_bin("kvs") .unwrap() .args(&["rm", "extra", "field"]) .assert() .failure(); } #[test] fn cli_invalid_subcommand() { Command::cargo_bin("kvs") .unwrap() .args(&["unknown", "subcommand"]) .assert() .failure(); } // Should get previously stored value. #[test] fn get_stored_value() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let mut store = KvStore::open(temp_dir.path())?; store.set("key1".to_owned(), "value1".to_owned())?; store.set("key2".to_owned(), "value2".to_owned())?; assert_eq!(store.get("key1".to_owned())?, Some("value1".to_owned())); assert_eq!(store.get("key2".to_owned())?, Some("value2".to_owned())); // Open from disk again and check persistent data. drop(store); let mut store = KvStore::open(temp_dir.path())?; assert_eq!(store.get("key1".to_owned())?, Some("value1".to_owned())); assert_eq!(store.get("key2".to_owned())?, Some("value2".to_owned())); Ok(()) } // Should overwrite existent value. #[test] fn overwrite_value() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let mut store = KvStore::open(temp_dir.path())?; store.set("key1".to_owned(), "value1".to_owned())?; assert_eq!(store.get("key1".to_owned())?, Some("value1".to_owned())); store.set("key1".to_owned(), "value2".to_owned())?; assert_eq!(store.get("key1".to_owned())?, Some("value2".to_owned())); // Open from disk again and check persistent data. drop(store); let mut store = KvStore::open(temp_dir.path())?; assert_eq!(store.get("key1".to_owned())?, Some("value2".to_owned())); store.set("key1".to_owned(), "value3".to_owned())?; assert_eq!(store.get("key1".to_owned())?, Some("value3".to_owned())); Ok(()) } // Should get `None` when getting a non-existent key. #[test] fn get_non_existent_value() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let mut store = KvStore::open(temp_dir.path())?; store.set("key1".to_owned(), "value1".to_owned())?; assert_eq!(store.get("key2".to_owned())?, None); // Open from disk again and check persistent data. drop(store); let mut store = KvStore::open(temp_dir.path())?; assert_eq!(store.get("key2".to_owned())?, None); Ok(()) } #[test] fn remove_non_existent_key() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let mut store = KvStore::open(temp_dir.path())?; assert!(store.remove("key1".to_owned()).is_err()); Ok(()) } #[test] fn remove_key() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let mut store = KvStore::open(temp_dir.path())?; store.set("key1".to_owned(), "value1".to_owned())?; assert!(store.remove("key1".to_owned()).is_ok()); assert_eq!(store.get("key1".to_owned())?, None); Ok(()) } // Insert data until total size of the directory decreases. // Test data correctness after compaction. #[test] fn compaction() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let mut store = KvStore::open(temp_dir.path())?; let dir_size = || { let entries = WalkDir::new(temp_dir.path()).into_iter(); let len: walkdir::Result = entries .map(|res| { res.and_then(|entry| entry.metadata()) .map(|metadata| metadata.len()) }) .sum(); len.expect("fail to get directory size") }; let mut current_size = dir_size(); for iter in 0..1000 { for key_id in 0..1000 { let key = format!("key{}", key_id); let value = format!("{}", iter); store.set(key, value)?; } let new_size = dir_size(); if new_size > current_size { current_size = new_size; continue; } // Compaction triggered. drop(store); // reopen and check content. let mut store = KvStore::open(temp_dir.path())?; for key_id in 0..1000 { let key = format!("key{}", key_id); assert_eq!(store.get(key)?, Some(format!("{}", iter))); } return Ok(()); } panic!("No compaction detected"); } ================================================ FILE: courses/rust/projects/project-3/Cargo.toml ================================================ [package] name = "kvs" version = "0.1.0" authors = ["Yilin Chen "] description = "A key-value store" edition = "2018" [dependencies] clap = "2.33.0" structopt = "0.2.15" failure = "0.1.5" serde = { version = "1.0.89", features = ["derive"] } serde_json = "1.0.39" log = "0.4.6" env_logger = "0.6.1" sled = "0.34.6" [dev-dependencies] assert_cmd = "0.11" criterion = "0.3" predicates = "1.0.0" rand = "0.6.5" tempfile = "3.0.7" walkdir = "2.2.7" [[bench]] name = "engine_bench" harness = false ================================================ FILE: courses/rust/projects/project-3/README.md ================================================ # PNA Rust Project 3: Synchronous client-server networking **Task**: Create a _single-threaded_, persistent key/value store _server and client with synchronous networking over a custom protocol_. **Goals**: - Create a client-server application - Write a custom protocol with `std` networking APIs - Introduce logging to the server - Implement pluggable backends with traits - Benchmark the hand-written backend against `sled` **Topics**: `std::net`, logging, traits, benchmarking. - [Introduction](#user-content-introduction) - [Project spec](#user-content-project-spec) - [Project setup](#user-content-project-setup) - [Part 1: Command line parsing](#user-content-part-1-command-line-parsing) - [Part 2: Logging](#user-content-part-2-logging) - [Part 3: Client-server networking setup](#user-content-part-3-client-server-networking-setup) - [Part 4: Implementing commands across the network](#user-content-part-4-implementing-commands-across-the-network) - [Part 5: Pluggable storage engines](#user-content-part-5-pluggable-storage-engines) - [Part 6: Benchmarking](#user-content-part-6-benchmarking) ## Introduction In this project you will create a simple key/value server and client. They will communicate with a custom networking protocol of your design. You will emit logs using standard logging crates, and handle errors correctly across the network boundary. Once you have a working client-server architecture, then you will abstract the storage engine behind traits, and compare the performance of yours to the [`sled`] engine. ## Project spec The cargo project, `kvs`, builds a command-line key-value store client called `kvs-client`, and a key-value store server called `kvs-server`, both of which in turn call into a library called `kvs`. The client speaks to the server over a custom protocol. The `kvs-server` executable supports the following command line arguments: - `kvs-server [--addr IP-PORT] [--engine ENGINE-NAME]` Start the server and begin listening for incoming connections. `--addr` accepts an IP address, either v4 or v6, and a port number, with the format `IP:PORT`. If `--addr` is not specified then listen on `127.0.0.1:4000`. If `--engine` is specified, then `ENGINE-NAME` must be either "kvs", in which case the built-in engine is used, or "sled", in which case sled is used. If this is the first run (there is no data previously persisted) then the default value is "kvs"; if there is previously persisted data then the default is the engine already in use. If data was previously persisted with a different engine than selected, print an error and exit with a non-zero exit code. Print an error and return a non-zero exit code on failure to bind a socket, if `ENGINE-NAME` is invalid, if `IP-PORT` does not parse as an address. - `kvs-server -V` Print the version. The `kvs-client` executable supports the following command line arguments: - `kvs-client set [--addr IP-PORT]` Set the value of a string key to a string. `--addr` accepts an IP address, either v4 or v6, and a port number, with the format `IP:PORT`. If `--addr` is not specified then connect on `127.0.0.1:4000`. Print an error and return a non-zero exit code on server error, or if `IP-PORT` does not parse as an address. - `kvs-client get [--addr IP-PORT]` Get the string value of a given string key. `--addr` accepts an IP address, either v4 or v6, and a port number, with the format `IP:PORT`. If `--addr` is not specified then connect on `127.0.0.1:4000`. Print an error and return a non-zero exit code on server error, or if `IP-PORT` does not parse as an address. - `kvs-client rm [--addr IP-PORT]` Remove a given string key. `--addr` accepts an IP address, either v4 or v6, and a port number, with the format `IP:PORT`. If `--addr` is not specified then connect on `127.0.0.1:4000`. Print an error and return a non-zero exit code on server error, or if `IP-PORT` does not parse as an address. A "key not found" is also treated as an error in the "rm" command. - `kvs-client -V` Print the version. All error messages should be printed to stderr. The `kvs` library contains four types: - `KvsClient` - implements the functionality required for `kvs-client` to speak to `kvs-server` - `KvsServer` - implements the functionality to serve responses to `kvs-client` from `kvs-server` - `KvsEngine` trait - defines the storage interface called by `KvsServer` - `KvStore` - implements by hand the `KvsEngine` trait - `SledKvsEngine` - implements `KvsEngine` for the [`sled`] storage engine. [`sled`]: https://github.com/spacejam/sled The design of `KvsClient` and `KvsServer` are up to you, and will be informed by the design of your network protocol. The test suite does not directly use either type, but only exercises them via the CLI. The `KvsEngine` trait supports the following methods: - `KvsEngine::set(&mut self, key: String, value: String) -> Result<()>` Set the value of a string key to a string. Return an error if the value is not written successfully. - `KvsEngine::get(&mut self, key: String) -> Result>` Get the string value of a string key. If the key does not exist, return `None`. Return an error if the value is not read successfully. - `KvsEngine::remove(&mut self, key: String) -> Result<()>` Remove a given string key. Return an error if the key does not exit or value is not read successfully. When setting a key to a value, `KvStore` writes the `set` command to disk in a sequential log. When removing a key, `KvStore` writes the `rm` command to the log. On startup, the commands in the log are re-evaluated and the log pointer (file offset) of the last command to set each key recorded in the in-memory index. When retrieving a value for a key with the `get` command, it searches the index, and if found then loads from the log, and evaluates, the command at the corresponding log pointer. When the size of the uncompacted log entries reach a given threshold, `KvStore` compacts it into a new log, removing redundant entries to reclaim disk space. ## Project setup Continuing from your previous project, delete your previous `tests` directory and copy this project's `tests` directory into its place. This project should contain a library named `kvs`, and two executables, `kvs-server` and `kvs-client`. You need the following dev-dependencies in your `Cargo.toml`: ```toml [dev-dependencies] assert_cmd = "0.11" criterion = "0.3" predicates = "1.0.0" rand = "0.6.5" tempfile = "3.0.7" walkdir = "2.2.7" ``` As with previous projects, add enough definitions that the test suite builds. ## Part 1: Command line parsing There's little new about the command line parsing in this project compared to previous projects. The `kvs-client` binary accepts the same command line arguments as in previous projects. And now `kvs-server` has its own set of command line arguments to handle, as described previously in the spec. _Stub out the `kvs-server` command line handling._ ## Part 2: Logging Production server applications tend to have robust and configurable logging. So now we're going to add logging to `kvs-server`, and as we continue will look for useful information to log. During development it is common to use logging at the `debug!` and `trace!` levels for "println debugging". There are two prominent logging systems in Rust: [`log`] and [`slog`]. Both export similar macros for logging at different levels, like `error!`, `info!` etc. Both are extensible, supporting different backends, for logging to the console, logging to file, logging to the system log, etc. [`log`]: https://docs.rs/log/ [`slog`]: https://docs.rs/slog/ The major difference is that `log` is fairly simple, logging only formatted strings; `slog` is feature-rich, and supports "structured logging", where log entries are typed and serialized in easily-parsed formats. `log` dates from the very earliest days of Rust, where it was part of the compiler, then part of the standard library, and finally released as its own crate. It is maintained by the Rust Project. `slog` is newer and maintained independently. Both are widely used. For both systems, one needs to select a "sink" crate, one that the logger sends logs to for display or storage. _Read about both of them, choose the one that appeals to you, add them as dependencies, then modify `kvs-server` to initialize logging on startup, prior to command-line parsing._ Set it up to output to stderr (sending the logs elsewhere additionally is fine, but they must go to stderr to pass the tests in this project). On startup log the server's version number. Also log the configuration. For now that means the IP address and port, and the name of the storage engine. ## Part 3: Client-server networking setup Next we're going to set up the networking. For this project you are going to be using the basic TCP/IP networking APIs in `std::net`: [`TcpListener`] and [`TcpStream`]. [`TcpListener`]: https://doc.rust-lang.org/std/net/struct.TcpListener.html [`TcpStream`]: https://doc.rust-lang.org/std/net/struct.TcpStream.html For this project, the server is synchronous and single-threaded. That means that you will listen on a socket, then accept connections, and execute and respond to commands one at a time. In the future we will re-visit this decision multiple times on our journey toward an asynchronous, multi-threaded, and high-performance database. Think about your manual testing workflow. Now that there are two executables to deal with, you'll need a way to run them both at the same time. If you are like many, you will use two terminals, running `cargo run --bin kvs-server` in one, where it runs until you press CTRL-D, and `cargo run --bin kvs-client` in the other. This is a good opportunity to use the logging macros for debugging. Go ahead and log information about every accepted connection. _Before thinking about the protocol, modify `kvs-server` to listen for and accept connections, and `kvs-client` to initiate connections._ ## Part 4: Implementing commands across the network In the last project you defined the commands your database accepts, and learned how to serialize and deserialize them to and from the log with `serde`. Now it's time to implement the key/value store over the network, remotely executing commands that until now have been implemented within a single process. As with the file I/O you worked on in the last project to create the log, you will be serializing and streaming commands with the `Read` and `Write` traits. You are going to design a network protocol. There are a number of ways to get data in and out of a TCP stream, and a number of decisions to make. Is it a text-based protocol, binary? How is the data translated from its format in memory to its format byte-stream format? Is there a single request per connection, or many? Keep in mind that it must support successful results and errors, and there are two kinds of errors now: the ones generated by your storage engine, as well as network errors. All the details of the protocol are up to you. The test suite does not care at all how the data gets from one end to the other, just that the results are correct. _Write your network protocol._ ## Part 5: Pluggable storage engines Your database has a storage engine, `KvStore`, implemented by you. Now you are going to add a second storage engine. There are multiple reasons to do so: - Different workloads require different performance characteristics. Some storage engines may work better than other based on the workload. - It creates a familiar framework for comparing different backends. - It gives us an excuse to create and work with traits. - It gives us an excuse to write some comparative benchmarks! So you are going to _extract_ a new trait, `KvsEngine`, from the `KvStore` interface. This is a classic _refactoring_, where existing code is transformed into a new form incrementally. When refactoring you will generally want to break the work up into the smallest changes that will continue to build and work. Here is the API you need to end up with: - `trait KvsEngine` has `get`, `set` and `remove` methods with the same signatures as `KvStore`. - `KvStore` implements `KvsEngine`, and no longer has `get`, `set` and `remove` methods of its own. - There is a new implementation of `KvsEngine`, `SledKvsEngine`. You need to fill its `get` and `set` methods using the `sled` library later. It's likely that you have already stubbed out the definitions for these if your tests are building. _Now is the time to fill them in._ Break down your refactoring into an intentional sequence of changes, and make sure the project continues to build and pass previously-passing tests before continuing. As one final step, you need to consider what happens when `kvs-server` is started with one engine, is killed, then restarted with a different engine. This case can only result in an error, and you need to figure out how to detect the case to report the error. The test `cli_wrong_engine` reflects this scenario. ## Part 6: Benchmarking As the course progresses we will increasingly concern ourselves with the performance of the database, exploring the impact of different architectures. You are encouraged to go beyond the model described herein and experiment with your own optimizations. Performance work requires benchmarking, so now we're going to get started on that. There are many ways to benchmark databases, with standard test suites like [ycsb] and [sysbench]. In Rust benchmarking starts with the builtin tooling, so we will start there. [ycsb]: https://github.com/brianfrankcooper/YCSB [sysbench]: https://github.com/akopytov/sysbench Cargo supports benchmarking with `cargo bench`. The benchmarks may either be written using Rust's built in benchmark harness, or an external one. The built-in harness creates benchmarks from functions with the `#[bench]` attribute. It cannot be used on the Rust stable channel though, and is only documented briefly in [the unstable book][tb] and the [`test` crate docs][tc]. It is though widely used throughout the Rust ecosystem — crates that use it, even if they compile with stable releases, do benchmarking with nightly releases. [tb]: https://doc.rust-lang.org/stable/unstable-book/library-features/test.html [tc]: https://doc.rust-lang.org/stable/test/index.html That system though is effectively deprecated — it is not being updated and will seemingly never be promoted to the stable release channel. There are better benchmark harnesses for Rust anyway. The one you will use is [criterion]. And you will use it to satisfy your curiosity about the performance of your `kvs` engine compared to the `sled` engine. These benchmarking tools work by defining a benchmarking function, and within that function iterating through a loop that performs the operation to be benchmarking. The benchmarking tool will iterate as many times as it needs to in order to know the duration of the operation with statistical significance. See this basic example from the criterion guide: ```rust fn criterion_benchmark(c: &mut Criterion) { c.bench_function("fib 20", |b| { b.iter(|| { fibonacci(20) }); }); } ``` The call to `bench_function` defines the benchmark, and the call to `iter` defines the code that is run for the benchmark. Code before and after the call to `iter` is not timed. [criterion]: https://docs.rs/criterion Prepare for writing benchmarks by creating a file called `benches/benches.rs`. Like `tests/tests.rs`, cargo will automatically find this file and compile it as a benchmark. Start by writing the following benchmarks: - `kvs_write` - With the kvs engine, write 100 values with random keys of length 1-100000 bytes and random values of length 1-100000 bytes. - `sled_write`- With the sled engine, write 100 values with random keys of length 1-100000 bytes and random values of length 1-100000 bytes. - `kvs_read` - With the kvs engine, read 1000 values from previously written keys, with keys and values of random length. - `sled_read` - With the sled engine, read 1000 values from previously written keys, with keys and values of random length. (As an alternative to writing 4 benchmarks, you may also choose to write 2 benchmarks parameterized over the engine, as [described in the criterion manual][pb]). [pb]: https://bheisler.github.io/criterion.rs/book/user_guide/benchmarking_with_inputs.html These are underspecified, and there's a fair bit of nuance to implementing them in a useful way. We need to consider at least three factors: - What code should be timed (and be written inside the benchmark loop), and what code should not (and be written outside the benchmark loop)? - How to make the loop run identically for each iteration, despite using "random" numbers. - In the "read" benchmarks, how to read from the same set of "random" keys that were written previously. These are all inter-related: some code needs to be carefully selected as un-timed setup code, and the seed values for random number generators need to be re-used appropriately. In all cases, operations that may return errors should assert (with `assert!`) that they did not return an error; and in the read case, "get" operations should assert that the key was found. Random numbers can be generated with the [`rand`] crate. [`rand`]: https://docs.rs/crate/rand/ Once you have your benchmarks, run them with `cargo bench`. _Write the above benchmarks, and compare the results between `kvs` and `sled`._ _Note: please run the benchmarks on an otherwise unloaded machine. Benchmark results are very sensitive to the environment they are run in, and while the criterion library does its best to compensate for "noise", benchmarks are best done on a clean machine without other active processes. If you have a spare machine just for development, use that. If not, an AWS or other cloud instance may produce more consistent results than your local desktop._ Nice coding, friend. Enjoy a nice break. ================================================ FILE: courses/rust/projects/project-3/benches/engine_bench.rs ================================================ use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; use kvs::{KvStore, KvsEngine, SledKvsEngine}; use rand::prelude::*; use sled; use tempfile::TempDir; fn set_bench(c: &mut Criterion) { let mut group = c.benchmark_group("set_bench"); group.bench_function("kvs", |b| { b.iter_batched( || { let temp_dir = TempDir::new().unwrap(); (KvStore::open(temp_dir.path()).unwrap(), temp_dir) }, |(mut store, _temp_dir)| { for i in 1..(1 << 12) { store.set(format!("key{}", i), "value".to_string()).unwrap(); } }, BatchSize::SmallInput, ) }); group.bench_function("sled", |b| { b.iter_batched( || { let temp_dir = TempDir::new().unwrap(); (SledKvsEngine::new(sled::open(&temp_dir).unwrap()), temp_dir) }, |(mut db, _temp_dir)| { for i in 1..(1 << 12) { db.set(format!("key{}", i), "value".to_string()).unwrap(); } }, BatchSize::SmallInput, ) }); group.finish(); } fn get_bench(c: &mut Criterion) { let mut group = c.benchmark_group("get_bench"); for i in &vec![8, 12, 16, 20] { group.bench_with_input(format!("kvs_{}", i), i, |b, i| { let temp_dir = TempDir::new().unwrap(); let mut store = KvStore::open(temp_dir.path()).unwrap(); for key_i in 1..(1 << i) { store .set(format!("key{}", key_i), "value".to_string()) .unwrap(); } let mut rng = SmallRng::from_seed([0; 16]); b.iter(|| { store .get(format!("key{}", rng.gen_range(1, 1 << i))) .unwrap(); }) }); } for i in &vec![8, 12, 16, 20] { group.bench_with_input(format!("sled_{}", i), i, |b, i| { let temp_dir = TempDir::new().unwrap(); let mut db = SledKvsEngine::new(sled::open(&temp_dir).unwrap()); for key_i in 1..(1 << i) { db.set(format!("key{}", key_i), "value".to_string()) .unwrap(); } let mut rng = SmallRng::from_seed([0; 16]); b.iter(|| { db.get(format!("key{}", rng.gen_range(1, 1 << i))).unwrap(); }) }); } group.finish(); } criterion_group!(benches, set_bench, get_bench); criterion_main!(benches); ================================================ FILE: courses/rust/projects/project-3/src/bin/kvs-client.rs ================================================ use clap::AppSettings; use kvs::{KvsClient, Result}; use std::net::SocketAddr; use std::process::exit; use structopt::StructOpt; const DEFAULT_LISTENING_ADDRESS: &str = "127.0.0.1:4000"; const ADDRESS_FORMAT: &str = "IP:PORT"; #[derive(StructOpt, Debug)] #[structopt( name = "kvs-client", raw(global_settings = "&[\ AppSettings::DisableHelpSubcommand,\ AppSettings::VersionlessSubcommands]") )] struct Opt { #[structopt(subcommand)] command: Command, } #[derive(StructOpt, Debug)] enum Command { #[structopt(name = "get", about = "Get the string value of a given string key")] Get { #[structopt(name = "KEY", help = "A string key")] key: String, #[structopt( long, help = "Sets the server address", raw(value_name = "ADDRESS_FORMAT"), raw(default_value = "DEFAULT_LISTENING_ADDRESS"), parse(try_from_str) )] addr: SocketAddr, }, #[structopt(name = "set", about = "Set the value of a string key to a string")] Set { #[structopt(name = "KEY", help = "A string key")] key: String, #[structopt(name = "VALUE", help = "The string value of the key")] value: String, #[structopt( long, help = "Sets the server address", raw(value_name = "ADDRESS_FORMAT"), raw(default_value = "DEFAULT_LISTENING_ADDRESS"), parse(try_from_str) )] addr: SocketAddr, }, #[structopt(name = "rm", about = "Remove a given string key")] Remove { #[structopt(name = "KEY", help = "A string key")] key: String, #[structopt( long, help = "Sets the server address", raw(value_name = "ADDRESS_FORMAT"), raw(default_value = "DEFAULT_LISTENING_ADDRESS"), parse(try_from_str) )] addr: SocketAddr, }, } fn main() { let opt = Opt::from_args(); if let Err(e) = run(opt) { eprintln!("{}", e); exit(1); } } fn run(opt: Opt) -> Result<()> { match opt.command { Command::Get { key, addr } => { let mut client = KvsClient::connect(addr)?; if let Some(value) = client.get(key)? { println!("{}", value); } else { println!("Key not found"); } } Command::Set { key, value, addr } => { let mut client = KvsClient::connect(addr)?; client.set(key, value)?; } Command::Remove { key, addr } => { let mut client = KvsClient::connect(addr)?; client.remove(key)?; } } Ok(()) } ================================================ FILE: courses/rust/projects/project-3/src/bin/kvs-server.rs ================================================ use clap::arg_enum; use kvs::*; use log::LevelFilter; use log::{error, info, warn}; use std::env::current_dir; use std::fs; use std::net::SocketAddr; use std::process::exit; use structopt::StructOpt; const DEFAULT_LISTENING_ADDRESS: &str = "127.0.0.1:4000"; const DEFAULT_ENGINE: Engine = Engine::kvs; #[derive(StructOpt, Debug)] #[structopt(name = "kvs-server")] struct Opt { #[structopt( long, help = "Sets the listening address", value_name = "IP:PORT", raw(default_value = "DEFAULT_LISTENING_ADDRESS"), parse(try_from_str) )] addr: SocketAddr, #[structopt( long, help = "Sets the storage engine", value_name = "ENGINE-NAME", raw(possible_values = "&Engine::variants()") )] engine: Option, } arg_enum! { #[allow(non_camel_case_types)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] enum Engine { kvs, sled } } fn main() { env_logger::builder().filter_level(LevelFilter::Info).init(); let mut opt = Opt::from_args(); let res = current_engine().and_then(move |curr_engine| { if opt.engine.is_none() { opt.engine = curr_engine; } if curr_engine.is_some() && opt.engine != curr_engine { error!("Wrong engine!"); exit(1); } run(opt) }); if let Err(e) = res { error!("{}", e); exit(1); } } fn run(opt: Opt) -> Result<()> { let engine = opt.engine.unwrap_or(DEFAULT_ENGINE); info!("kvs-server {}", env!("CARGO_PKG_VERSION")); info!("Storage engine: {}", engine); info!("Listening on {}", opt.addr); // write engine to engine file fs::write(current_dir()?.join("engine"), format!("{}", engine))?; match engine { Engine::kvs => run_with_engine(KvStore::open(current_dir()?)?, opt.addr), Engine::sled => run_with_engine(SledKvsEngine::new(sled::open(current_dir()?)?), opt.addr), } } fn run_with_engine(engine: E, addr: SocketAddr) -> Result<()> { let server = KvsServer::new(engine); server.run(addr) } fn current_engine() -> Result> { let engine = current_dir()?.join("engine"); if !engine.exists() { return Ok(None); } match fs::read_to_string(engine)?.parse() { Ok(engine) => Ok(Some(engine)), Err(e) => { warn!("The content of engine file is invalid: {}", e); Ok(None) } } } ================================================ FILE: courses/rust/projects/project-3/src/client.rs ================================================ use crate::common::{GetResponse, RemoveResponse, Request, SetResponse}; use crate::{KvsError, Result}; use serde::Deserialize; use serde_json::de::{Deserializer, IoRead}; use std::io::{BufReader, BufWriter, Write}; use std::net::{TcpStream, ToSocketAddrs}; /// Key value store client pub struct KvsClient { reader: Deserializer>>, writer: BufWriter, } impl KvsClient { /// Connect to `addr` to access `KvsServer`. pub fn connect(addr: A) -> Result { let tcp_reader = TcpStream::connect(addr)?; let tcp_writer = tcp_reader.try_clone()?; Ok(KvsClient { reader: Deserializer::from_reader(BufReader::new(tcp_reader)), writer: BufWriter::new(tcp_writer), }) } /// Get the value of a given key from the server. pub fn get(&mut self, key: String) -> Result> { serde_json::to_writer(&mut self.writer, &Request::Get { key })?; self.writer.flush()?; let resp = GetResponse::deserialize(&mut self.reader)?; match resp { GetResponse::Ok(value) => Ok(value), GetResponse::Err(msg) => Err(KvsError::StringError(msg)), } } /// Set the value of a string key in the server. pub fn set(&mut self, key: String, value: String) -> Result<()> { serde_json::to_writer(&mut self.writer, &Request::Set { key, value })?; self.writer.flush()?; let resp = SetResponse::deserialize(&mut self.reader)?; match resp { SetResponse::Ok(_) => Ok(()), SetResponse::Err(msg) => Err(KvsError::StringError(msg)), } } /// Remove a string key in the server. pub fn remove(&mut self, key: String) -> Result<()> { serde_json::to_writer(&mut self.writer, &Request::Remove { key })?; self.writer.flush()?; let resp = RemoveResponse::deserialize(&mut self.reader)?; match resp { RemoveResponse::Ok(_) => Ok(()), RemoveResponse::Err(msg) => Err(KvsError::StringError(msg)), } } } ================================================ FILE: courses/rust/projects/project-3/src/common.rs ================================================ use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] pub enum Request { Get { key: String }, Set { key: String, value: String }, Remove { key: String }, } #[derive(Debug, Serialize, Deserialize)] pub enum GetResponse { Ok(Option), Err(String), } #[derive(Debug, Serialize, Deserialize)] pub enum SetResponse { Ok(()), Err(String), } #[derive(Debug, Serialize, Deserialize)] pub enum RemoveResponse { Ok(()), Err(String), } ================================================ FILE: courses/rust/projects/project-3/src/engines/kvs.rs ================================================ use std::collections::{BTreeMap, HashMap}; use std::fs::{self, File, OpenOptions}; use std::io::{self, BufReader, BufWriter, Read, Seek, SeekFrom, Write}; use std::ops::Range; use std::path::{Path, PathBuf}; use serde::{Deserialize, Serialize}; use serde_json::Deserializer; use super::KvsEngine; use crate::{KvsError, Result}; use std::ffi::OsStr; const COMPACTION_THRESHOLD: u64 = 1024 * 1024; /// The `KvStore` stores string key/value pairs. /// /// Key/value pairs are persisted to disk in log files. Log files are named after /// monotonically increasing generation numbers with a `log` extension name. /// A `BTreeMap` in memory stores the keys and the value locations for fast query. /// /// ```rust /// # use kvs::{KvStore, Result}; /// # fn try_main() -> Result<()> { /// use std::env::current_dir; /// use kvs::KvsEngine; /// let mut store = KvStore::open(current_dir()?)?; /// store.set("key".to_owned(), "value".to_owned())?; /// let val = store.get("key".to_owned())?; /// assert_eq!(val, Some("value".to_owned())); /// # Ok(()) /// # } /// ``` pub struct KvStore { // directory for the log and other data path: PathBuf, // map generation number to the file reader readers: HashMap>, // writer of the current log writer: BufWriterWithPos, current_gen: u64, index: BTreeMap, // the number of bytes representing "stale" commands that could be // deleted during a compaction uncompacted: u64, } impl KvStore { /// Opens a `KvStore` with the given path. /// /// This will create a new directory if the given one does not exist. /// /// # Errors /// /// It propagates I/O or deserialization errors during the log replay. pub fn open(path: impl Into) -> Result { let path = path.into(); fs::create_dir_all(&path)?; let mut readers = HashMap::new(); let mut index = BTreeMap::new(); let gen_list = sorted_gen_list(&path)?; let mut uncompacted = 0; for &gen in &gen_list { let mut reader = BufReaderWithPos::new(File::open(log_path(&path, gen))?)?; uncompacted += load(gen, &mut reader, &mut index)?; readers.insert(gen, reader); } let current_gen = gen_list.last().unwrap_or(&0) + 1; let writer = new_log_file(&path, current_gen, &mut readers)?; Ok(KvStore { path, readers, writer, current_gen, index, uncompacted, }) } /// Clears stale entries in the log. pub fn compact(&mut self) -> Result<()> { // increase current gen by 2. current_gen + 1 is for the compaction file let compaction_gen = self.current_gen + 1; self.current_gen += 2; self.writer = self.new_log_file(self.current_gen)?; let mut compaction_writer = self.new_log_file(compaction_gen)?; let mut new_pos = 0; // pos in the new log file for cmd_pos in &mut self.index.values_mut() { let reader = self .readers .get_mut(&cmd_pos.gen) .expect("Cannot find log reader"); if reader.pos != cmd_pos.pos { reader.seek(SeekFrom::Start(cmd_pos.pos))?; } let mut entry_reader = reader.take(cmd_pos.len); let len = io::copy(&mut entry_reader, &mut compaction_writer)?; *cmd_pos = (compaction_gen, new_pos..new_pos + len).into(); new_pos += len; } compaction_writer.flush()?; // remove stale log files let stale_gens: Vec<_> = self .readers .keys() .filter(|&&gen| gen < compaction_gen) .cloned() .collect(); for stale_gen in stale_gens { self.readers.remove(&stale_gen); fs::remove_file(log_path(&self.path, stale_gen))?; } self.uncompacted = 0; Ok(()) } /// Create a new log file with given generation number and add the reader to the readers map. /// /// Returns the writer to the log. fn new_log_file(&mut self, gen: u64) -> Result> { new_log_file(&self.path, gen, &mut self.readers) } } impl KvsEngine for KvStore { /// Sets the value of a string key to a string. /// /// If the key already exists, the previous value will be overwritten. /// /// # Errors /// /// It propagates I/O or serialization errors during writing the log. fn set(&mut self, key: String, value: String) -> Result<()> { let cmd = Command::set(key, value); let pos = self.writer.pos; serde_json::to_writer(&mut self.writer, &cmd)?; self.writer.flush()?; if let Command::Set { key, .. } = cmd { if let Some(old_cmd) = self .index .insert(key, (self.current_gen, pos..self.writer.pos).into()) { self.uncompacted += old_cmd.len; } } if self.uncompacted > COMPACTION_THRESHOLD { self.compact()?; } Ok(()) } /// Gets the string value of a given string key. /// /// Returns `None` if the given key does not exist. fn get(&mut self, key: String) -> Result> { if let Some(cmd_pos) = self.index.get(&key) { let reader = self .readers .get_mut(&cmd_pos.gen) .expect("Cannot find log reader"); reader.seek(SeekFrom::Start(cmd_pos.pos))?; let cmd_reader = reader.take(cmd_pos.len); if let Command::Set { value, .. } = serde_json::from_reader(cmd_reader)? { Ok(Some(value)) } else { Err(KvsError::UnexpectedCommandType) } } else { Ok(None) } } /// Removes a given key. /// /// # Error /// /// It returns `KvsError::KeyNotFound` if the given key is not found. /// /// It propagates I/O or serialization errors during writing the log. fn remove(&mut self, key: String) -> Result<()> { if self.index.contains_key(&key) { let cmd = Command::remove(key); serde_json::to_writer(&mut self.writer, &cmd)?; self.writer.flush()?; if let Command::Remove { key } = cmd { let old_cmd = self.index.remove(&key).expect("key not found"); self.uncompacted += old_cmd.len; } Ok(()) } else { Err(KvsError::KeyNotFound) } } } /// Create a new log file with given generation number and add the reader to the readers map. /// /// Returns the writer to the log. fn new_log_file( path: &Path, gen: u64, readers: &mut HashMap>, ) -> Result> { let path = log_path(&path, gen); let writer = BufWriterWithPos::new( OpenOptions::new() .create(true) .write(true) .append(true) .open(&path)?, )?; readers.insert(gen, BufReaderWithPos::new(File::open(&path)?)?); Ok(writer) } /// Returns sorted generation numbers in the given directory fn sorted_gen_list(path: &Path) -> Result> { let mut gen_list: Vec = fs::read_dir(&path)? .flat_map(|res| -> Result<_> { Ok(res?.path()) }) .filter(|path| path.is_file() && path.extension() == Some("log".as_ref())) .flat_map(|path| { path.file_name() .and_then(OsStr::to_str) .map(|s| s.trim_end_matches(".log")) .map(str::parse::) }) .flatten() .collect(); gen_list.sort_unstable(); Ok(gen_list) } /// Load the whole log file and store value locations in the index map. /// /// Returns how many bytes can be saved after a compaction. fn load( gen: u64, reader: &mut BufReaderWithPos, index: &mut BTreeMap, ) -> Result { // To make sure we read from the beginning of the file let mut pos = reader.seek(SeekFrom::Start(0))?; let mut stream = Deserializer::from_reader(reader).into_iter::(); let mut uncompacted = 0; // number of bytes that can be saved after a compaction while let Some(cmd) = stream.next() { let new_pos = stream.byte_offset() as u64; match cmd? { Command::Set { key, .. } => { if let Some(old_cmd) = index.insert(key, (gen, pos..new_pos).into()) { uncompacted += old_cmd.len; } } Command::Remove { key } => { if let Some(old_cmd) = index.remove(&key) { uncompacted += old_cmd.len; } // the "remove" command itself can be deleted in the next compaction // so we add its length to `uncompacted` uncompacted += new_pos - pos; } } pos = new_pos; } Ok(uncompacted) } fn log_path(dir: &Path, gen: u64) -> PathBuf { dir.join(format!("{}.log", gen)) } /// Struct representing a command #[derive(Serialize, Deserialize, Debug)] enum Command { Set { key: String, value: String }, Remove { key: String }, } impl Command { fn set(key: String, value: String) -> Command { Command::Set { key, value } } fn remove(key: String) -> Command { Command::Remove { key } } } /// Represents the position and length of a json-serialized command in the log struct CommandPos { gen: u64, pos: u64, len: u64, } impl From<(u64, Range)> for CommandPos { fn from((gen, range): (u64, Range)) -> Self { CommandPos { gen, pos: range.start, len: range.end - range.start, } } } struct BufReaderWithPos { reader: BufReader, pos: u64, } impl BufReaderWithPos { fn new(mut inner: R) -> Result { let pos = inner.seek(SeekFrom::Current(0))?; Ok(BufReaderWithPos { reader: BufReader::new(inner), pos, }) } } impl Read for BufReaderWithPos { fn read(&mut self, buf: &mut [u8]) -> io::Result { let len = self.reader.read(buf)?; self.pos += len as u64; Ok(len) } } impl Seek for BufReaderWithPos { fn seek(&mut self, pos: SeekFrom) -> io::Result { self.pos = self.reader.seek(pos)?; Ok(self.pos) } } struct BufWriterWithPos { writer: BufWriter, pos: u64, } impl BufWriterWithPos { fn new(mut inner: W) -> Result { let pos = inner.seek(SeekFrom::Current(0))?; Ok(BufWriterWithPos { writer: BufWriter::new(inner), pos, }) } } impl Write for BufWriterWithPos { fn write(&mut self, buf: &[u8]) -> io::Result { let len = self.writer.write(buf)?; self.pos += len as u64; Ok(len) } fn flush(&mut self) -> io::Result<()> { self.writer.flush() } } impl Seek for BufWriterWithPos { fn seek(&mut self, pos: SeekFrom) -> io::Result { self.pos = self.writer.seek(pos)?; Ok(self.pos) } } ================================================ FILE: courses/rust/projects/project-3/src/engines/mod.rs ================================================ //! This module provides various key value storage engines. use crate::Result; /// Trait for a key value storage engine. pub trait KvsEngine { /// Sets the value of a string key to a string. /// /// If the key already exists, the previous value will be overwritten. fn set(&mut self, key: String, value: String) -> Result<()>; /// Gets the string value of a given string key. /// /// Returns `None` if the given key does not exist. fn get(&mut self, key: String) -> Result>; /// Removes a given key. /// /// # Errors /// /// It returns `KvsError::KeyNotFound` if the given key is not found. fn remove(&mut self, key: String) -> Result<()>; } mod kvs; mod sled; pub use self::kvs::KvStore; pub use self::sled::SledKvsEngine; ================================================ FILE: courses/rust/projects/project-3/src/engines/sled.rs ================================================ use super::KvsEngine; use crate::{KvsError, Result}; use sled::{Db, Tree}; /// Wrapper of `sled::Db` #[derive(Clone)] pub struct SledKvsEngine(Db); impl SledKvsEngine { /// Creates a `SledKvsEngine` from `sled::Db`. pub fn new(db: Db) -> Self { SledKvsEngine(db) } } impl KvsEngine for SledKvsEngine { fn set(&mut self, key: String, value: String) -> Result<()> { let tree: &Tree = &self.0; tree.insert(key, value.into_bytes()).map(|_| ())?; tree.flush()?; Ok(()) } fn get(&mut self, key: String) -> Result> { let tree: &Tree = &self.0; Ok(tree .get(key)? .map(|i_vec| AsRef::<[u8]>::as_ref(&i_vec).to_vec()) .map(String::from_utf8) .transpose()?) } fn remove(&mut self, key: String) -> Result<()> { let tree: &Tree = &self.0; tree.remove(key)?.ok_or(KvsError::KeyNotFound)?; tree.flush()?; Ok(()) } } ================================================ FILE: courses/rust/projects/project-3/src/error.rs ================================================ use failure::Fail; use std::io; use std::string::FromUtf8Error; /// Error type for kvs #[derive(Fail, Debug)] pub enum KvsError { /// IO error #[fail(display = "IO error: {}", _0)] Io(#[cause] io::Error), /// Serialization or deserialization error #[fail(display = "serde_json error: {}", _0)] Serde(#[cause] serde_json::Error), /// Removing non-existent key error #[fail(display = "Key not found")] KeyNotFound, /// Unexpected command type error. /// It indicated a corrupted log or a program bug. #[fail(display = "Unexpected command type")] UnexpectedCommandType, /// Key or value is invalid UTF-8 sequence #[fail(display = "UTF-8 error: {}", _0)] Utf8(#[cause] FromUtf8Error), /// Sled error #[fail(display = "sled error: {}", _0)] Sled(#[cause] sled::Error), /// Error with a string message #[fail(display = "{}", _0)] StringError(String), } impl From for KvsError { fn from(err: io::Error) -> KvsError { KvsError::Io(err) } } impl From for KvsError { fn from(err: serde_json::Error) -> KvsError { KvsError::Serde(err) } } impl From for KvsError { fn from(err: FromUtf8Error) -> KvsError { KvsError::Utf8(err) } } impl From for KvsError { fn from(err: sled::Error) -> KvsError { KvsError::Sled(err) } } /// Result type for kvs pub type Result = std::result::Result; ================================================ FILE: courses/rust/projects/project-3/src/lib.rs ================================================ #![deny(missing_docs)] //! A simple key/value store. pub use client::KvsClient; pub use engines::{KvStore, KvsEngine, SledKvsEngine}; pub use error::{KvsError, Result}; pub use server::KvsServer; mod client; mod common; mod engines; mod error; mod server; ================================================ FILE: courses/rust/projects/project-3/src/server.rs ================================================ use crate::common::{GetResponse, RemoveResponse, Request, SetResponse}; use crate::{KvsEngine, Result}; use log::{debug, error}; use serde_json::Deserializer; use std::io::{BufReader, BufWriter, Write}; use std::net::{TcpListener, TcpStream, ToSocketAddrs}; /// The server of a key value store. pub struct KvsServer { engine: E, } impl KvsServer { /// Create a `KvsServer` with a given storage engine. pub fn new(engine: E) -> Self { KvsServer { engine } } /// Run the server listening on the given address pub fn run(mut self, addr: A) -> Result<()> { let listener = TcpListener::bind(addr)?; for stream in listener.incoming() { match stream { Ok(stream) => { if let Err(e) = self.serve(stream) { error!("Error on serving client: {}", e); } } Err(e) => error!("Connection failed: {}", e), } } Ok(()) } fn serve(&mut self, tcp: TcpStream) -> Result<()> { let peer_addr = tcp.peer_addr()?; let reader = BufReader::new(&tcp); let mut writer = BufWriter::new(&tcp); let req_reader = Deserializer::from_reader(reader).into_iter::(); macro_rules! send_resp { ($resp:expr) => {{ let resp = $resp; serde_json::to_writer(&mut writer, &resp)?; writer.flush()?; debug!("Response sent to {}: {:?}", peer_addr, resp); };}; } for req in req_reader { let req = req?; debug!("Receive request from {}: {:?}", peer_addr, req); match req { Request::Get { key } => send_resp!(match self.engine.get(key) { Ok(value) => GetResponse::Ok(value), Err(e) => GetResponse::Err(format!("{}", e)), }), Request::Set { key, value } => send_resp!(match self.engine.set(key, value) { Ok(_) => SetResponse::Ok(()), Err(e) => SetResponse::Err(format!("{}", e)), }), Request::Remove { key } => send_resp!(match self.engine.remove(key) { Ok(_) => RemoveResponse::Ok(()), Err(e) => RemoveResponse::Err(format!("{}", e)), }), }; } Ok(()) } } ================================================ FILE: courses/rust/projects/project-3/tests/cli.rs ================================================ use assert_cmd::prelude::*; use predicates::str::{contains, is_empty}; use std::fs::{self, File}; use std::process::Command; use std::sync::mpsc; use std::thread; use std::time::Duration; use tempfile::TempDir; // `kvs-client` with no args should exit with a non-zero code. #[test] fn client_cli_no_args() { let temp_dir = TempDir::new().unwrap(); let mut cmd = Command::cargo_bin("kvs-client").unwrap(); cmd.current_dir(&temp_dir).assert().failure(); } #[test] fn client_cli_invalid_get() { let temp_dir = TempDir::new().unwrap(); Command::cargo_bin("kvs-client") .unwrap() .args(&["get"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "extra", "field"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key", "--addr", "invalid-addr"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key", "--unknown-flag"]) .current_dir(&temp_dir) .assert() .failure(); } #[test] fn client_cli_invalid_set() { let temp_dir = TempDir::new().unwrap(); Command::cargo_bin("kvs-client") .unwrap() .args(&["set"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["set", "missing_field"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["set", "key", "value", "extra_field"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["set", "key", "value", "--addr", "invalid-addr"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key", "--unknown-flag"]) .current_dir(&temp_dir) .assert() .failure(); } #[test] fn client_cli_invalid_rm() { let temp_dir = TempDir::new().unwrap(); Command::cargo_bin("kvs-client") .unwrap() .args(&["rm"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["rm", "extra", "field"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["rm", "key", "--addr", "invalid-addr"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["rm", "key", "--unknown-flag"]) .current_dir(&temp_dir) .assert() .failure(); } #[test] fn client_cli_invalid_subcommand() { let temp_dir = TempDir::new().unwrap(); Command::cargo_bin("kvs-client") .unwrap() .args(&["unknown"]) .current_dir(&temp_dir) .assert() .failure(); } // `kvs-client -V` should print the version #[test] fn client_cli_version() { let temp_dir = TempDir::new().unwrap(); let mut cmd = Command::cargo_bin("kvs-client").unwrap(); cmd.args(&["-V"]) .current_dir(&temp_dir) .assert() .stdout(contains(env!("CARGO_PKG_VERSION"))); } // `kvs-server -V` should print the version #[test] fn server_cli_version() { let temp_dir = TempDir::new().unwrap(); let mut cmd = Command::cargo_bin("kvs-server").unwrap(); cmd.args(&["-V"]) .current_dir(&temp_dir) .assert() .stdout(contains(env!("CARGO_PKG_VERSION"))); } #[test] fn cli_log_configuration() { let temp_dir = TempDir::new().unwrap(); let stderr_path = temp_dir.path().join("stderr"); let mut cmd = Command::cargo_bin("kvs-server").unwrap(); let mut child = cmd .args(&["--engine", "kvs", "--addr", "127.0.0.1:4001"]) .current_dir(&temp_dir) .stderr(File::create(&stderr_path).unwrap()) .spawn() .unwrap(); thread::sleep(Duration::from_secs(1)); child.kill().expect("server exited before killed"); let content = fs::read_to_string(&stderr_path).expect("unable to read from stderr file"); assert!(content.contains(env!("CARGO_PKG_VERSION"))); assert!(content.contains("kvs")); assert!(content.contains("127.0.0.1:4001")); } #[test] fn cli_wrong_engine() { // sled first, kvs second { let temp_dir = TempDir::new().unwrap(); let mut cmd = Command::cargo_bin("kvs-server").unwrap(); let mut child = cmd .args(&["--engine", "sled", "--addr", "127.0.0.1:4002"]) .current_dir(&temp_dir) .spawn() .unwrap(); thread::sleep(Duration::from_secs(1)); child.kill().expect("server exited before killed"); let mut cmd = Command::cargo_bin("kvs-server").unwrap(); cmd.args(&["--engine", "kvs", "--addr", "127.0.0.1:4003"]) .current_dir(&temp_dir) .assert() .failure(); } // kvs first, sled second { let temp_dir = TempDir::new().unwrap(); let mut cmd = Command::cargo_bin("kvs-server").unwrap(); let mut child = cmd .args(&["--engine", "kvs", "--addr", "127.0.0.1:4002"]) .current_dir(&temp_dir) .spawn() .unwrap(); thread::sleep(Duration::from_secs(1)); child.kill().expect("server exited before killed"); let mut cmd = Command::cargo_bin("kvs-server").unwrap(); cmd.args(&["--engine", "sled", "--addr", "127.0.0.1:4003"]) .current_dir(&temp_dir) .assert() .failure(); } } fn cli_access_server(engine: &str, addr: &str) { let (sender, receiver) = mpsc::sync_channel(0); let temp_dir = TempDir::new().unwrap(); let mut server = Command::cargo_bin("kvs-server").unwrap(); let mut child = server .args(&["--engine", engine, "--addr", addr]) .current_dir(&temp_dir) .spawn() .unwrap(); let handle = thread::spawn(move || { let _ = receiver.recv(); // wait for main thread to finish child.kill().expect("server exited before killed"); }); thread::sleep(Duration::from_secs(1)); Command::cargo_bin("kvs-client") .unwrap() .args(&["set", "key1", "value1", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(is_empty()); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key1", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout("value1\n"); Command::cargo_bin("kvs-client") .unwrap() .args(&["set", "key1", "value2", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(is_empty()); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key1", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout("value2\n"); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key2", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(contains("Key not found")); Command::cargo_bin("kvs-client") .unwrap() .args(&["rm", "key2", "--addr", addr]) .current_dir(&temp_dir) .assert() .failure() .stderr(contains("Key not found")); Command::cargo_bin("kvs-client") .unwrap() .args(&["set", "key2", "value3", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(is_empty()); Command::cargo_bin("kvs-client") .unwrap() .args(&["rm", "key1", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(is_empty()); sender.send(()).unwrap(); handle.join().unwrap(); // Reopen and check value let (sender, receiver) = mpsc::sync_channel(0); let mut server = Command::cargo_bin("kvs-server").unwrap(); let mut child = server .args(&["--engine", engine, "--addr", addr]) .current_dir(&temp_dir) .spawn() .unwrap(); let handle = thread::spawn(move || { let _ = receiver.recv(); // wait for main thread to finish child.kill().expect("server exited before killed"); }); thread::sleep(Duration::from_secs(1)); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key2", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(contains("value3")); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key1", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(contains("Key not found")); sender.send(()).unwrap(); handle.join().unwrap(); } #[test] fn cli_access_server_kvs_engine() { cli_access_server("kvs", "127.0.0.1:4004"); } #[test] fn cli_access_server_sled_engine() { cli_access_server("sled", "127.0.0.1:4005"); } ================================================ FILE: courses/rust/projects/project-3/tests/kv_store.rs ================================================ use kvs::{KvStore, KvsEngine, Result}; use tempfile::TempDir; use walkdir::WalkDir; // Should get previously stored value #[test] fn get_stored_value() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let mut store = KvStore::open(temp_dir.path())?; store.set("key1".to_owned(), "value1".to_owned())?; store.set("key2".to_owned(), "value2".to_owned())?; assert_eq!(store.get("key1".to_owned())?, Some("value1".to_owned())); assert_eq!(store.get("key2".to_owned())?, Some("value2".to_owned())); // Open from disk again and check persistent data drop(store); let mut store = KvStore::open(temp_dir.path())?; assert_eq!(store.get("key1".to_owned())?, Some("value1".to_owned())); assert_eq!(store.get("key2".to_owned())?, Some("value2".to_owned())); Ok(()) } // Should overwrite existent value #[test] fn overwrite_value() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let mut store = KvStore::open(temp_dir.path())?; store.set("key1".to_owned(), "value1".to_owned())?; assert_eq!(store.get("key1".to_owned())?, Some("value1".to_owned())); store.set("key1".to_owned(), "value2".to_owned())?; assert_eq!(store.get("key1".to_owned())?, Some("value2".to_owned())); // Open from disk again and check persistent data drop(store); let mut store = KvStore::open(temp_dir.path())?; assert_eq!(store.get("key1".to_owned())?, Some("value2".to_owned())); store.set("key1".to_owned(), "value3".to_owned())?; assert_eq!(store.get("key1".to_owned())?, Some("value3".to_owned())); Ok(()) } // Should get `None` when getting a non-existent key #[test] fn get_non_existent_value() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let mut store = KvStore::open(temp_dir.path())?; store.set("key1".to_owned(), "value1".to_owned())?; assert_eq!(store.get("key2".to_owned())?, None); // Open from disk again and check persistent data drop(store); let mut store = KvStore::open(temp_dir.path())?; assert_eq!(store.get("key2".to_owned())?, None); Ok(()) } #[test] fn remove_non_existent_key() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let mut store = KvStore::open(temp_dir.path())?; assert!(store.remove("key1".to_owned()).is_err()); Ok(()) } #[test] fn remove_key() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let mut store = KvStore::open(temp_dir.path())?; store.set("key1".to_owned(), "value1".to_owned())?; assert!(store.remove("key1".to_owned()).is_ok()); assert_eq!(store.get("key1".to_owned())?, None); Ok(()) } // Insert data until total size of the directory decreases. // Test data correctness after compaction. #[test] fn compaction() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let mut store = KvStore::open(temp_dir.path())?; let dir_size = || { let entries = WalkDir::new(temp_dir.path()).into_iter(); let len: walkdir::Result = entries .map(|res| { res.and_then(|entry| entry.metadata()) .map(|metadata| metadata.len()) }) .sum(); len.expect("fail to get directory size") }; let mut current_size = dir_size(); for iter in 0..1000 { for key_id in 0..1000 { let key = format!("key{}", key_id); let value = format!("{}", iter); store.set(key, value)?; } let new_size = dir_size(); if new_size > current_size { current_size = new_size; continue; } // Compaction triggered drop(store); // reopen and check content let mut store = KvStore::open(temp_dir.path())?; for key_id in 0..1000 { let key = format!("key{}", key_id); assert_eq!(store.get(key)?, Some(format!("{}", iter))); } return Ok(()); } panic!("No compaction detected"); } ================================================ FILE: courses/rust/projects/project-4/Cargo.toml ================================================ [package] name = "kvs" version = "0.1.0" authors = ["Yilin Chen "] description = "A key-value store" edition = "2018" [dependencies] clap = "2.33.0" structopt = "0.2.15" failure = "0.1.5" serde = { version = "1.0.89", features = ["derive"] } serde_json = "1.0.39" log = "0.4.6" env_logger = "0.6.1" sled = "0.34.6" crossbeam = "0.7.1" rayon = "1.0.3" num_cpus = "1.10.0" crossbeam-skiplist = { git = "https://github.com/crossbeam-rs/crossbeam.git", branch = "master" } [dev-dependencies] assert_cmd = "0.11" criterion = "0.3" crossbeam-utils = "0.6.5" predicates = "1.0.0" rand = "0.6.5" tempfile = "3.0.7" walkdir = "2.2.7" panic-control = "0.1.4" ================================================ FILE: courses/rust/projects/project-4/README.md ================================================ # PNA Rust Project 4: Concurrency and parallelism **Task**: Create a _multi-threaded_, persistent key/value store server and client with synchronous networking over a custom protocol. **Goals**: - Write a simple thread pool - Use channels for cross-thread communication - Share data structures with locks - Perform read operations without locks - Benchmark single-threaded vs multithreaded **Topics**: thread pools, channels, locks, lock-free data structures, atomics, parameterized benchmarking. - [Introduction](#user-content-introduction) - [Project spec](#user-content-project-spec) - [Project setup](#user-content-project-setup) - [Background: blocking and multithreading](#user-content-background-blocking-and-multithreading) - [Part 1: Multithreading](#user-content-part-1-multithreading) - [Part 2: Creating a shared `KvsEngine`](#user-content-part-2-creating-a-shared-kvsengine) - [Part 3: Adding multithreading to `KvServer`](#user-content-part-3-adding-multithreading-to-kvserver) - [Part 4: Creating a real thread pool](#user-content-part-4-creating-a-real-thread-pool) - [So how do you build a thread pool?](#user-content-so-how-do-you-build-a-thread-pool) - [Part 5: Abstracted thread pools](#user-content-part-5-abstracted-thread-pools) - [Part 6: Evaluating your thread pool](#user-content-part-6-evaluating-your-thread-pool) - [Ok, now to the first two benchmarks](#user-content-ok-now-to-the-first-two-benchmarks) - [Part 7: Evaluating other thread pools and engines](#user-content-part-7-evaluating-other-thread-pools-and-engines) - [Extension 1: Comparing functions](#user-content-extension-1-comparing-functions) - [Background: The limits of locks](#user-content-background-the-limits-of-locks) - [Part 8: Lock-free readers](#user-content-part-8-lock-free-readers) - [Explaining our example data structure](#user-content-explaining-our-example-data-structure) - [Strategies for breaking up locks](#user-content-strategies-for-breaking-up-locks) - [Understand and maintain sequential consistency](#user-content-understand-and-maintain-sequential-consistency) - [Identify immutable values](#user-content-identify-immutable-values) - [Duplicate values instead of sharing](#user-content-duplicate-values-instead-of-sharing) - [Break up data structures by role](#user-content-break-up-data-structures-by-role) - [Use specialized concurrent data structures](#user-content-use-specialized-concurrent-data-structures) - [Postpone cleanup until later](#user-content-postpone-cleanup-until-later) - [Share flags and counters with atomics](#user-content-share-flags-and-counters-with-atomics) - [Implement lock-free readers](#user-content-implement-lock-free-readers) ## Introduction In this project you will create a simple key/value server and client that communicate over a custom protocol. The server will use synchronous networking, and will respond to multiple requests using increasingly sophisticated concurrent implementations. The in-memory index will become a concurrent data structure, shared by all threads, and compaction will be done on a dedicated thread, to reduce latency of individual requests. ## Project spec The cargo project, `kvs`, builds a command-line key-value store client called `kvs-client`, and a key-value store server called `kvs-server`, both of which in turn call into a library called `kvs`. The client speaks to the server over a custom protocol. The interface to the CLI is the same as in the [previous project]. The difference this time is in the concurrent implementation, which will be described as we work through it. [previous project]: ../project-3/README.md The library interface is nearly the same except for two things. First this time all the `KvsEngine`, `KvStore`, etc. methods take `&self` instead of `&mut self`, and now it implements `Clone`. This is common with concurrent data structures. Why is that? It's not that we're not going to be writing immutable code. It _is_ though going to be shared across threads. Why might that preclude using `&mut self` in the method signatures? If you don't know now, it will become obvious by the end of this project. The second is that the library in this project contains a new _trait_, `ThreadPool`. It contains the following methods: - `ThreadPool::new(threads: u32) -> Result` Creates a new thread pool, immediately spawning the specified number of threads. Returns an error if any thread fails to spawn. All previously-spawned threads are terminated. - `ThreadPool::spawn(&self, job: F) where F: FnOnce() + Send + 'static` Spawn a function into the threadpool. Spawning always succeeds, but if the function panics the threadpool continues to operate with the same number of threads — the thread count is not reduced nor is the thread pool destroyed, corrupted or invalidated. By the end of this project there will be several implementations of this trait, and you will again perform benchmarking to compare them. This project should not require any changes at all to the client code. ## Project setup Continuing from your previous project, delete your previous `tests` directory and copy this project's `tests` directory into its place. This project should contain a library named `kvs`, and two executables, `kvs-server` and `kvs-client`. You need the following dev-dependencies in your `Cargo.toml`: ```toml [dev-dependencies] assert_cmd = "0.11" criterion = "0.2.11" crossbeam-utils = "0.6.5" predicates = "1.0.0" rand = "0.6.5" tempfile = "3.0.7" walkdir = "2.2.7" panic-control = "0.1.4" ``` As with previous projects, add enough definitions that the test suite builds. ## Background: blocking and multithreading Until now you have serviced all of your requests, both read and write (e.g. "get" and "set"), on a single thread. In other words, all the requests in your database are _serialized_. Using a diagram we are going to repeat through this project, the flow of time looks like this: ``` thread + +--------+--------+--------+--------+ T1 | | R1 | R2 | W1 | W2 | + +--------+--------+--------+--------+ --> read/write reqs over time --> ``` Both read and write operations may require _blocking_. Blocking is when a thread stops execution while waiting for access to a resource, like data from a file, or a variable protected by a lock. While a thread is blocked on one task it can't make progress on another task. So in an I/O heavy system, any particular request might spend _most_ of its time just waiting on the operating system and memory control to move data to and from the disk: ``` +---------+----------------------------+---------+ R1 | working | waiting for data ... | working | +---------+----------------------------+---------+ --> time --> ``` The simplest way to put the CPU back to work while one request is blocked is to service requests on multiple threads, so that ideally our requests are all processed concurrently, and — if we have enough CPUs — in parallel: ``` thread + +--------+ T1 | | R1 | | +--------+ T2 | | R2 | | +--------+ T3 | | W1 | | +--------+ T4 | | W2 | + +--------+ --> read/write reqs over time --> ``` So that will be the focus of this project — to process requests in parallel. ## Part 1: Multithreading Your first try at introducing concurrency is going to be the simplest: spawning a new thread per incoming connection, and responding to the request on that connection, then letting the thread exit. What performance benefits will distributing work across threads provide? How do you expect latency will be affected? What about throughput? The first step is to write a `ThreadPool` implementation for this naive approach, where `ThreadPool::spawn` will create a new thread for each spawned job. Call it `NaiveThreadPool` (it's not _really_ even a thread _pool_ since this implementation is not going to reuse threads between jobs, but it needs to conform to our trait for later comparisons). We aren't focusing on a more sophisticated implementation now because simply integrating this solution into our existing design is going to take some effort. Note that the `ThreadPool::new` constructor takes a `threads` argument specifying the number of threads in the pool. In this implementation it will be unused. _Go ahead and implement this version of `ThreadPool` now_, then we'll integrate it into the new `KvStore`. **Test cases to complete**: - `thread_pool::naive_thread_pool_*` ## Part 2: Creating a shared `KvsEngine` Before we can integrate the `NaiveThreadPool` into `KvServer` we have to make the `KvsEngine` trait and the `KvStore` implementation (for now you can ignore the `SledKvsEngine` from the previous project, but you can optionally re-implement it as an extension to this project). Recall from the project spec that, this time, our `KvsEngine` takes `self` as `&self` instead of `&mut self` as previously, It also implements `Clone`, which must be done explicitly for each implementation, as well as `Send + 'static`, implicit properties of the definition of each implementation. More concretely, it looks like ```rust pub trait KvsEngine: Clone + Send + 'static { fn set(&self, key: String, value: String) -> Result<()>; fn get(&self, key: String) -> Result>; fn remove(&self, key: String) -> Result<()>; } ``` This gives us a lot of clues about the implementation strategy we're pursuing. First, think about why the engine needs to implement `Clone` when we have a multithreaded implementation. Consider the design of other concurrent data types in Rust, like [`Arc`]. Now think about why that makes us use `&self` instead of `&mut self`. What do you know about shared mutable state? By the end of this project be sure you understand the implications here — _this is what Rust is all about_. [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html In this model, `KvsEngine` behaves like a _handle_ to another object, and because that object is shared between threads, it probably needs to live on the [heap], and because that shared state can't be mutable it needs to be protected by some synchronization primitive. [heap]: https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap So, _move the data inside your implementation of `KvsEngine`, `KvStore` onto the heap using a thread-safe shared pointer type and protect it behind a lock of your choosing_. Since `SledKvsEngine` implements `KvsEngine` it may also need to change. At this point your single-threaded `kvs-server` should work once again, but now with a `KvsEngine` that can later be shared across threads. **Test cases to complete**: - `kv_store::concurrent_*` ## Part 3: Adding multithreading to `KvServer` Let's quickly review our architecture here: `KvServer` sets up a TCP socket and begins listening on it; when it receives a request it deserializes it and calls some implementation of the `KvsEngine` trait to store or retrieve data; then it sends back the response. The details of how `KvsEngine` works don't matter to `KvServer`. So in the last project you probably created a loop vaguelly like: ```rust let listener = TcpListener::bind(addr)?; for stream in listener.incoming() { let cmd = self.read_cmd(&stream); let resp = self.process_cmd(cmd); self.respond(&stream, resp); } ``` _Well, now you just need to do the same thing, but spawn all the work inside the loop into your `NaiveThreadPool`_. The database query and the response are both handled on a different thread than the TCP listener. This offloads most of the hard work to other threads, allowing the recieving thread to process more requests. It should increase throughput, at least on multi-core machines. Again, you should still have a working client/server key-value store, now multithreaded. ## Part 4: Creating a real thread pool So now that you've got your multithreaded architecture in place, it's time to write a real thread pool. You probably wouldn't write your own thread pool in practice as there exist thread pool crates that are well-tested, but it is a useful exercise to gain experience with concurrency in general. Later in this project you will, as we did with the engine in the previous project, abstract the thread pool and compare the performance of yours with an existing. So, what is a thread pool? It's nothing complicated. Instead of creating a new thread for every multithreaded job to be performed, a thread pool maintains a "pool" of threads, and reuses those threads instead of creating a new one. But why? It's entirely about performance. Reusing threads saves a small amount of performance, but when writing high-performance applications, every bit counts. Imagine what it takes to make a new thread: You've got to have a call stack for that thread to run on. That call stack must be allocated. Allocations are pretty cheap, but not as cheap as no allocation. How that call stack is allocated depends on details of the operating system and runtime, but can involve locks and syscalls. Syscalls again are not _that_ expensive, but they are expensive when we're dealing with Rust levels of performance — reducing syscalls is a common source of easy optimizations. That stack then has to be carefully initialized so that first [stack frame] contains the appropriate values for the base pointer and whatever else is needed in the stack's initial [function prologue][fp]. In Rust the stack needs to be configured with a [guard page] to prevent stack overflows, preserving memory safety. That takes two more syscalls, [to `mmap` and to `mprotect`][mp] (though on Linux in particular, those two syscalls are avoided). [guard page]: https://docs.microsoft.com/en-us/windows/desktop/Memory/creating-guard-pages [fp]: https://en.wikipedia.org/wiki/Function_prologue [stack frame]: https://en.wikipedia.org/wiki/Stack_frame [2mb]: https://github.com/rust-lang/rust/blob/6635fbed4ca8c65822f99e994735bd1877fb063e/src/libstd/sys/unix/thread.rs#L12 [mp]: https://github.com/rust-lang/rust/blob/6635fbed4ca8c65822f99e994735bd1877fb063e/src/libstd/sys/unix/thread.rs#L315 That's just setting up the callstack. It's at least another syscall to create the new thread, at which point the kernel must do its own internal accounting for the new thread. In Rust, the C [libpthread] library handles most of this complexity. Then at some point the OS performs a [context switch] onto the new stack, and the thread runs. When the thread terminates all that work needs to be undone again. With a thread pool, all that setup overhead is only done for a few threads, and subsequent jobs are simply context switches into existing threads in the pool. [libpthread]: https://www.gnu.org/software/hurd/libpthread.html [context switch]: https://en.wikipedia.org/wiki/Context_switch ### So how do you build a thread pool? There are many strategies and tradeoffs, but for this exercise you are going to use a single shared queue to distribute work to idle threads. That means that your "producer", the thread that accepts network connections, sends jobs to a single queue (or channel), and the "consumers", every idle thread in the pool, read from that channel waiting for a job to execute. This is the very simplest work scheduling strategy, but it can be effective. What are the downsides? You have three important considerations here: 1) _which data structure to use to distribute the work_ — it's going to be a queue, and there is going to be one sender ("producer"), the thread listening for TCP connections, and many recievers ("consumers"), the threads in the pool. 2) _how to deal with panicking jobs_ — your pool runs arbitrary work items. If a thread panics, the thread pool needs to recover in some way. 3) _how to deal with shutdown_ — when the `ThreadPool` object goes out of scope it needs to shut down every thread. It must not leave them idle. These concerns are all intertwined since dealing with each of them may involve communication and synchronization between threads. Some solutions will be simple, the solutions to each of these working together gracefully; some solutions will be complex, the solutions being independent and convoluted. Choose your data structures carefully and use their capabilities wisely. You will distribute work by sending messages over some concurrent queue type (a concurrent queue in Rust typically being a data structure with two connected types: sender types, and reciever types; and that can send between the two types any type that implements `Send` + `'static`). Messages in Rust are typically represented as enums, with variants for each possible message that can be sent, like: ```rust enum ThreadPoolMessage { RunJob(Box), Shutdown, } ``` This tends to be a simpler and more efficient solution than trying to "juggle" multiple channels for different purposes. Of course, if there is only one type of message, an enum is not necessary. Now, the above example may or may not be the full set of messages you need to manage your thread pool, depending on the design. In particular, shutting down can often be done implicitly if your queue returns a result indicating that the sender has been destroyed. There are many types of multithreaded queues. In Rust the most common is the [`mpsc`] channel, because it lives in Rust's standard library. This is a multi-producer, single consumer queue, so using it for your single-queue thread pool will require a lock of some kind. What's the downside of using a lock here? There are many other concurrent queue types in Rust, and each has pros and cons. If you are willing to take a lock on both producer and consumer sides, then you could even use a `Mutex`, but there's probably no reason to do that in production when better solutions exist. [`mpsc`]: https://doc.rust-lang.org/std/sync/mpsc/index.html _Historical note: the existence of channels in Rust's standard library is a bit of a curiosity, and is considered a mistake by some, as it betrays Rust's general philosophy of keeping the standard library minimal, focused on abstracting the operating system, and letting the crate ecosystem experiment with advanced data structures. Their presence is an artifact of Rust's development history and origins as a message-passing language like Go. Other libraries like [`crossbeam`] provide more sophisticated alternatives, and sometimes more suitable options_ 😉. [`crossbeam`]: https://github.com/crossbeam-rs/crossbeam Your thread pool will need to deal with the case where the spawned function panics — simply letting panics destroy the threads in your pool would quickly deplete its available threads. So if a thread in your pool panics you need to make sure that the total number of threads doesn't decrease. So what should you do? You have at least two options: let the thread die and spawn another, or catch the panic and keep the existing thread running. What are the tradeoffs? You've got to pick one, but leave a comment in your code explaining your choice. Some of the tools at your disposal are [`thread::spawn`], [`thread::panicking`], [`catch_unwind`], [`mpsc`] channels, [`Mutex`], [crossbeam's MPMC channels][mpmc], and `thread`s [`JoinHandle`]. You may use any of these, but probably not all. [`thread::spawn`]: https://doc.rust-lang.org/std/thread/fn.spawn.html [`thread::panicking`]: https://doc.rust-lang.org/std/thread/fn.panicking.html [`catch_unwind`]: https://doc.rust-lang.org/std/panic/fn.catch_unwind.html [`mpsc`]: https://doc.rust-lang.org/std/sync/mpsc/index.html [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html [mpmc]: https://docs.rs/crossbeam/0.7.1/crossbeam/channel/index.html [`JoinHandle`]: https://doc.rust-lang.org/std/thread/struct.JoinHandle.html _Create the `SharedQueueThreadPool` type, implementing `ThreadPool`_. **Test cases to complete**: - `shared_queue_thread_pool_*` Replace the `NaiveThreadPool` used by `KvServer` with `SharedQueueThreadPool`. Again your `kvs-server` should still work the same as previously, now with a slightly more clever multithreading model. This time you'll want to call the thread pool constructor with an appropriate number of threads. For now you can create a thread per CPU, using the [`num_cpus`] crate. We'll revisit the number of threads later. [`num_cpus`]: https://docs.rs/num_cpus/ ## Part 5: Abstracted thread pools As in the previous project where you created a `KvsEngine` abstraction to compare different implementations, now you are going to use the `ThreadPool` abstraction to do the same. If you haven't already, add a second type parameter to `KvServer` to represent the `ThreadPool` implementation, the constructor to accept the thread pool as its second argument, and use that threadpool to distribute the work. Finally create one more `ThreadPool` implementation, `RayonThreadPool`, using the `ThreadPool` type from the [`rayon`] crate. Rayon's thread pool uses a more sophisticated scheduling strategy called ["work stealing"][ws], and we'll expect it to perform better than ours, but who knows until we try! [`rayon`]: https://docs.rs/rayon/ [ws]: https://www.dre.vanderbilt.edu/~schmidt/PDF/work-stealing-dequeue.pdf ## Part 6: Evaluating your thread pool Now you are going to write _six_ benchmarks, one write-heavy workload comparing performance of `SharedQueueThreadPool` with varying numbers of threads, one read-heavy workload comparing the performance of `SharedQueueThreadPool` with varying number of threads; two more that use `RayonThreadPool` instead of of `SharedQueueThreadPool`, and finally, yet two more that use `RayonThreadPool` in conjunction with `SledKvsEngine`. It's not as much as work as it sounds — four of them are essentially duplicates of the first two. _Note: the next two sections describe a fairly complex set of benchmarks. They can be written (probably… nobody has done it yet), but it may be challenging both to understand and to write efficiently. These sections do introduce some useful criterion features, but if it's too overwhelming it's ok to skip [forward] (and file a bug about what didn't work for you). On the other hand, the difficulty here may present a good learning opportunity. Finally, implementing these benchmarks as described requires a way to shutdown `KvsServer` programmatically (i.e. without sending `SIGKILL` and letting the OS do it), which we have not previously discussed._ [forward]: #user-content-background-the-limit-of-locks So as part of this you will need to make sure the `SledKvsEngine` implementation you wrote as part of the previous project works again in this multithreaded context. It should be trivial as sled can be cloned and sent between threads, just like your engine. Hopefully the results will be interesting. Again you will use criterion. These are going to be _parameterized_ benchmarks, that is, single benchmarks that are run multiple times with different parameters. Criterion calls these [benchmarking with inputs][bi]. And the parameter to you benchmarks will be the number of threads in the thread pool. What you are attempting to test is the throughput of your server under various conditions. You will be sending many requests concurrently, waiting for the responses, then ending. One thing you should be curious about here is how the number of threads affects your throughput compared to the number of CPUs on your machine; how your threadpool compares to rayon's; and how your `KvStore` compares to `SledKvsEngine` in a multithreaded context. This will be somewhat complicated by the fact that your `KvsClient` is (probably) blocking, that is, it sends a request then waits for a response. If it was non-blocking, then you could send _many_ requests without waiting for responses, then collect the responses later. With a blocking `KvsClient` you will need to send each request in its own thread in order to saturate the server's capacity. When benchmarking it is important to understand exactly what code you are trying to measure, and to the greatest extent possible only measure that code. A benchmarker like criterion runs a single piece of code many times in a loop, measuring the time it takes through each loop. As such we want to put only the code we want to measure in the loop, and leave as much outside of the loop as we can. [bi]: https://bheisler.github.io/criterion.rs/book/user_guide/benchmarking_with_inputs.html So take this simple example of a criterion benchmark with inputs: ```rust let c = Criterion::default(); let inputs = &[1, 2, 3, 4, 5]; c.bench_function_over_inputs("example", |b, &&num| { b.iter(|| { // important measured work goes here }); }, inputs); ``` That `iter` calls your closure many times, measuring each iteration. But since you are going to need to set up a lot of threads beforehand, that is work that you don't want to measure. If you can do the setup only once for multiple iterations then the setup can go outside the closure, like ```rust let c = Criterion::default(); let inputs = &[1, 2, 3, 4, 5]; c.bench_function_over_inputs("example", |b, &&num| { // do setup here b.iter(|| { // important measured work goes here }); }, inputs); ``` The code inside the `b.iter` closure is what is measured, setup goes before. If the setup can't go before the loop, then another strategy is to make the amount of setup work for smaller than the amount of work you actually want to measure, by e.g. adding loops. Also consider that "teardown" of the benchmark, which will often mostly consist of running `drop` implementations, also has a cost. If you have a blocking client, you are going to need many threads for your clients, and you only have the opportunities to create those threads once, prior to the many iterations of your loop. So you'll need to set up a bunch of reusable threads before you iterate over the benchmark. Fortunately you have the perfect tool for that in your `SharedQueueThreadPool`. Set that up with a thread per request, and pair it with some channels to report back that the response is received, and you will have a suitable benchmark harness. ### Ok, now to the first two benchmarks We have said that this is a parameterized benchmark, and the parameter to the benchmark is the number of CPUs to use in the server's thread pool. We want to see what the throughput is like with just 1 thread, with 2, with 4, and then for every even number up to 2x the number of cores in your computer. Why 2x? Well, there may be benefits to having more threads than cores, and you are going to find out experimentally. For the write-heavy workload, during setup (the part that runs before the call to `b.iter(...)`), create the `KvServer`, with the thread pool containing the parameterized number of threads. Then write a workload that sets 1000 unique keys of the same length, all to the same value. Note that though the keys are different, for consistent results they need to be the same keys every benchmark loop. Then after each thread sets a value they should also `assert!` that the call was successful (to ensure there are no bugs under load), then indicate that it is done. When all threads are done the benchmarking thread continues and finishes that iteration. An obvious way to implement this signaling of completion is for each thread to send a message back to the benchmarking thread, but keep in mind that the signaling code is overhead unrelated to the code you are trying to measure, so it needs to do a minimal amount of work. Can you do it with only one message, or maybe with some other concurrent type that only signals the benchmarking thread once? Call this benchmark `write_queued_kvstore` (or whatever). For the read-heavy workload, during setup, create the `KvServer`, with the thread pool containing the parameterized number of threads, and create your client thread pool containing 1000 threads. Still in the setup phase, create yet another client and initialize 1000 unique keys of the same length, all to identical values. Then, during the benchmarking loop, from the client, spawn 1000 jobs that retrieve those same key/value pars, and then `assert!` that the result is correct. Finally, as before, send a message back to the benchmarking thread indicating that read is complete. Call this benchmark `read_queued_kvstore` (or whatever). **Whew. That was a lot of work**. So you can run this set of criterion benchmarks as usual with `cargo bench`. But this time you are going to do more. Since you are running the same benchmark over multiple parameters, representing the number of threads in your threadpool, what would be really nice is if we could see the effect of different thread counts in a nice graph. Oh, hey — criterion does that! Go back and read about [benchmarking with inputs][bi]. It explains how to see the graph of your benchmark against its inputs. What do you notice? What happens as your number of threads approaches the number of CPUs on your machine? What happens as the number of threads exceeds the number of threads on your machine? What do you think accounts for the trend you see? The results depend on many factors, so your results might be different from anybody elses. That's a good reason to always benchmark, and not speculate about performance. We can make educated guesses, but we don't know until we test. ## Part 7: Evaluating other thread pools and engines Ok. You've gotten the most difficult part of this benchmarking exercise out of the way. Now you've just got to do almost the same thing in a few more configurations. Take those two benchmarks you wrote previously, and just copy-and-past them three times. In all of them, change `SharedQueueThreadPool` to `RayonThreadPool`. The third and fourth, name `read/write_rayon_kvstore` (or whatever). These you will compare to the first two `SharedQueueThreadPool` implementations, to see the difference between yours and `RayonThreadPool`. The fourth and fifth, name `read/write_rayon_sledkvengine`, and change the engine to `SledKvsEngine`. These you will compare to the previous two to see how your `KvsEngine` compares to sled's in a multithreaded environment. As before, run and chart all these benchmarks. Compare them to each other as described above. How does your scheduler compare to rayon under various thread counts? How does your storage engine compare to sled under various thread counts? Are the results surprising? Can you imagine why the differences exist? ### Extension 1: Comparing functions Now you have identical benchmarks for three different thread pools, and you have run them and compared their performance yourself. Criterion has built-in support for comparing multiple implementations. Check out ["comparing functions"][cp] in the Criterion User Guide and modify your benchmarks so that criterion does the comparison itself. Check out those gorgeous graphs. [cp]: https://bheisler.github.io/criterion.rs/book/user_guide/comparing_functions.html ### Background: The limits of locks Earlier in this project, we suggested making your `KvsEngine` thread-safe by putting its internals behind a lock, on the heap. You probably realized immediately that this wasn't going to improve throughput because it traded one type of blocking for another — instead of _maybe_ blocking on disk access, it is now _definitely_ blocking on mutex access. So all we've achieved so far is this: ``` thread + +--------+ T1 | | R1 | | +-----------------+ T2 | | R2 | | +-----------------+ T3 | | W1 | | +-----------------+ T4 | | W2 | + +--------+ --> read/write reqs over time --> ``` In the previous section you benchmarked the multithreaded throughput of your engine vs. the `SledKvsEngine`. Hopefully what you discovered is that your multithreaded implementation performed significantly worse than the `sled` multithreaded implementation (if not, well, either you are super-awesome or `sled` has some problems). Adding multithreading has so far resulted in performance that is strictly worse than the single-threaded implementation — now you've got the added work of context switching between threads, and the guaranteed blocking imposed by the mutex. So for this part of the project, you are going to get a bit more sophisticated. Protecting the entire state behind a lock is easy — the entire state is always read and written atomically because only one client at a time has access to the entire state. But that also means that two threads that want to access the shared state must wait on each other. In other words, when `KvsEngine` is protected by a mutex then there is very little actual concurrency in the server, despite being multithreaded. High-performance, scalable, parallel software tends to avoid locks and lock contention as much as possible. Rust makes sophisticated and high-performance concurrency patterns easier than most languages (because you don't need to worry about data races and crashes), but it _does not_ protect you from making logical mistakes that would result in incorrect behavior. So you've still got to do some hard thinking about concurrency. Fortunately there are many sophisticated parallel-programming tools in the Rust crate ecosystem, so your task is usually just to understand what they are and how to put them together, not to understand how to write complex lock-free data structures of your own. Let's look at some progressively more sophisticated examples. We'll take an example single-threaded `KvStore` and consider how to make it thread-safe. Here's an example single-threaded `KvStore` like you might have created in earlier projects (this is a simplified version of the one in the course example project): ```rust pub struct KvStore { /// Directory for the log and other data path: PathBuf, /// The log reader reader: BufReaderWithPos, /// The log writer writer: BufWriterWithPos, /// The in-memory index from key to log pointer index: BTreeMap, /// The number of bytes representing "stale" commands that could be /// deleted during a compaction uncompacted: u64, } ``` And here's the simple multithreaded version, protecting everything with a lock. Hopefully what you've already written for this project looks something like this: ```rust #[derive(Clone)] pub struct KvStore(Arc>); #[derive(Clone)] pub struct SharedKvStore { /// Directory for the log and other data path: PathBuf, /// The log reader reader: BufReaderWithPos, /// The log writer writer: BufWriterWithPos, /// The in-memory index from key to log pointer index: BTreeMap, /// The number of bytes representing "stale" commands that could be /// deleted during a compaction uncompacted: u64, } ``` This `Arc>` solution is trivial, correct, and common: - The [`Arc`] puts the value on the heap so it can be shared between threads, and provides a `clone` method to create a "handle" to it for each thread. - The [`Mutex`] provides a way to regain write access to the value without having an existing `&mut` reference. [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html This is a perfectly reasonable solution for many cases. But in this case that mutex will be a source of _contention_ under load: the `Mutex` doesn't only serialize write access to `SharedKvStore`, but read access as well. Any thread that wants to work with `KvStore` needs to wait for the `Mutex` to be unlocked by another thread. Any requests will block any other concurrent request. What we _really_ want is to not have to take locks, or — if locks are necessary — for them to rarely contend with other threads. The next step up in sophistication from a `Mutex` is the [`RwLock`], the "reader-writer lock". This is another common type of lock that every programmer of parallel software must know. The improvement that a reader-writer lock makes over a mutex is that it allows _either_ any number of readers, _or_ a single writer. So in Rust terms, a `RwLock` will hand out any number of `&` pointers simultaneously, or a single `&mut` pointer. Readers still block on writers and writers still block on readers and other writers. [`RwLock`]: https://doc.rust-lang.org/std/sync/struct.RwLock.html In our database that means that all read requests can be satisfied concurrently, but when a single write request comes in, all other activity in the system stops and waits for it. Implementing this is basically as simple as swapping the `Mutex` for `RwLock`. And, considering our multi-threading diagram again, the resulting process flow looks like: ``` thread + +--------+ T1 | | R1 | | +--------+ T2 | | R2 | | +-----------------+ T3 | | W1 | | +-----------------+ T4 | | W2 | + +--------+ --> read/write reqs over time --> ``` It's better, since the readers never block each other, but you can do better than that still. ## Part 8: Lock-free readers for this project you are challenged to create readers that never take a lock, even with a concurrent writer. A read request can always be serviced, regardless of write requests. (Writers can still block on other writers for now — besides being a challenging parallel programming problem, the question of whether it even makes sense to write in parallel is a difficult one to answer). You want to end up with ``` thread + +--------+ T1 | | R1 | | +--------+ T2 | | R2 | | +--------+ T3 | | W1 | | +-----------------+ T4 | | W2 | + +--------+ --> read/write reqs over time --> ``` If we can acheive that then our readers will be lock-free: even while a single reader is blocked waiting for data from the filesystems all types of other operations, reads and writes, can proceed. Unfortunately, this will still not be enough to guarantee that the system can always service read requests. Think about what would happen if there are `N` blocked write requests on our thread pool of size `N`. You'll have to solve that later. For now, you are focused on removing the locks from readers. Unlike `Mutex` and `RwLock`, there is no single wrapper type that we can apply to the entire arbitrary shared state to achieve the goal of reading and writing concurrently (at least, not while also being performant). That means that we need to consider how each one of the fields of `SharedKvStore` is used, and pick the right synchronization scheme to allow all threads to make as much progress as we can, while still maintaining logical consistency of the data. This is where the difficult reasoning with multithreading really begins. If you remove that big lock, Rust is still going to protect you from [_data races_], but it is not going to help you maintain the logical consistency between the fields necessary to maintain the invariants of your data store. [_data races_]: https://blog.regehr.org/archives/490 So before thinking about the solution, let's think about our requirements. We need to: - Read from the index and from the disk, on multiple threads at a time; - Write commands to disk, while maintaining the index; - Read in parallel with writing, thus - In general, to guarantee that readers will always see a consistent state while reading in parallel with a writer, which means, - Maintaining an invariant that log pointers in the index always point to a valid command in the log, - Maintaining appropriant invariants for other bookkeeping, like the `uncompacted` variable in the following example; - Periodically compact our on-disk data, again while maintaining invariants for readers. The rest of this section is background on a variety of subjects that will be helpful to achieve the above, but that is the entire goal for the remaining project: modify `KvStore` to perform reads concurrently with writes. ### Explaining our example data structure In order to talk about this concretely, we're going to need an example of the data we're trying to protect and the invariants we're trying to maintain. So here's an example of a `KvStore` implementation and its fields. ```rust pub struct KvStore { /// Directory for the log and other data path: PathBuf, /// The log reader reader: BufReaderWithPos, /// The log writer writer: BufWriterWithPos, /// The in-memory index from key to log pointer index: BTreeMap, /// The number of bytes representing "stale" commands that could be /// deleted during a compaction uncompacted: u64, } ``` This is a simplified version of the example for this project. The purpose of the fields should be fairly clear: `path: PathBuf` is just the path to the directory where logs are stored. It never changes — it is immutable, and immutable types are `Sync` in Rust, so it doesn't even need any protection at all. Every thread can read it at once through a shared reference. `readers: HashMap>` is the read handle to the current log file. It needs to change to a new log file after compaction. `writer: BufWriterWithPos` is the write handle to the current log file. So any write needs mutable access to `writer`, and the compaction process needs to change the `writer` and the `current_gen`. `index: BTreeMap` is the in-memory index of every key in the database to its location in the index file. It is read from every reading thread, and written from every writing thread, potentially including during compaction. `uncompacted: u64` simply counts the number of "stale" commands in the logs that have been superceded by subsequent write commands, to know when to trigger compaction. In previous projects we didn't have to worry much about the interaction between writing, reading, and compaction producing inconsistent results, since they all happened on the same thread. Now if you are not careful with your data structure selection and their usage, it will be easy to corrupt the state of your database. ### Strategies for breaking up locks The key to advanced parallel programming is to know the tools available and when to use them. Here are some techniques we found useful while implementing this project, some of which you will need as well. They are discussed in the context of the example data structure presented above. #### Understand and maintain sequential consistency (Note that "sequential consistency" has a precise meaning, but here we're just talking generally about ensuring that things that need to happen in a specific sequence do so). Reasoning about parallel programs is mostly about understanding the "happens-before" relationships in your code. In this thread, what changes to shared data structures do I need to see before others? What changes to shared data structures do I need to expose to other threads before others? How do I ensure that? In single-threaded code reasoning about what happens before any particular line of code is trivial — if the code is written to happen before, then it happens before, if not, it happens after. But this isn't actually true at all, even in single-threaded code: both the CPU and the compiler will reorder code to make it run faster, the CPU operating on machine code, and the compiler operating on its internal representation prior to generating the machine code. In reality the actual code executed happens in a different order than you wrote it to execute, and it only appears to run the way you wrote it because both the CPU and compiler track _data dependencies_ and don't reorder any operations that depend on another. In multi-threaded code the compiler and CPU will _still_ reorder code under the same assumptions as single-threaded code, and your code will break entirely unless you tell the compiler via synchronized types and operations that it must not allow reordering. Any operation that must occur before or after another must be exlicitly arranged to do so with synchronized types or operations, whether they be locks, atomics or otherwise. In our example it's clear that the write to the file and the write to the index must be seen to occur in a specific order — what would happen if the index was updated before the file? Likewise, our example contains another bit of state, `uncompacted`. What's the impact of miscalculating the uncompacted size? It may not be so bad if the value of `uncompacted` can be seen to change before the data is committed to file, but it's a decision that has to be made for each value that is synchronized independently. #### Identify immutable values You've probably read a lot about immutability in Rust, and about how immutable values can be shared trivially between theads (they are `Sync`). Immutable values are the best for concurrency — just throw them behind an `Arc` and don't think about them again. In our example, `PathBuf` is immutable. #### Duplicate values instead of sharing Cloning sometimes has a bad reputation in Rust, particularly cloning types with arbitrary size, like `String`, and `Vec`. But cloning is often perfectly reasonable: it can be quite difficult to avoid clones in some situations, and CPUs are _very good_ at copying buffers of memory. Furthermore, considering our use case, the number of state copies needed to support the server is bounded by the number of threads in the threadpool. In our example, again `PathBuf` is easily clonable. Less obviously though, consider how to share access to files across threads. The [`File`] type requires mutable access for both reads and writes. So to share it across threads would require a lock that grants that mutable access. What is a `File` though? It's not actually a file — it's just a handle to the physical resource on disk, and it's fine to have multiple handles to the same file open at once. Note the API for `File` though — it doesn't implement `Clone`, and while it does have this enticing [`try_clone`] method, its semantics have some complex implications for multi-threaded applications. Does seeking a `File` affect another `File` that created by `try_clone` ? Please consider the differences between `File`s from `File::open` and `try_clone`. Using `try_clone` or `File::open`, it's your choice. [`pread`] may help. [`File`]: https://doc.rust-lang.org/std/fs/struct.File.html [`try_clone`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.try_clone [`pread`]: https://stackoverflow.com/questions/1687275/what-is-the-difference-between-read-and-pread-in-unix #### Break up data structures by role In our use case we have two clear roles: readers, and writers (and maybe a third for compactors). The logical separation of readers and writers into their own concurrent types is a common in Rust. Readers have their own data set to work with, and writers their own, and that provides a good opportunity for encapsulation, with all read operations beloning to one type and all write operations another. Making this distinction will further make it very obvious which resources are accessed by both, since the reader and writer will both carry shared handles to those resources. #### Use specialized concurrent data structures Just knowing what tools are available and in which scenarios to use them may be the most difficult part of parallel programming. Beyond the basic lock types tought to everybody in school, synchronized data types become increasingly specialized. In this project, since the in-memory index is some type of associative data structure (a.k.a. a "map"), like a tree or hash table, it's natural to ask whether there exist concurrent associative data structures. There are, and using them is key to completing this project. But how can you know that? The first step is ask whether concurrent maps exist. You could do this in `#beginners` on the [Rust Discord], but in this case searching "concurrent map" on the web will definitely give the answer. That's the easy part, finding the right concurrent map _in Rust_ is harder. A good first step is to learch [libs.rs]. libs.rs is like crates.io but where crates.io contains all published libraries, libs.rs is curated to contain only libraries that are well-regarded by ... well, somebody. So if it's on libs.rs then that's one indication that the library is usable, another is the download count on [crates.io] — in general, more downloaded crates are more tested than less downloaded crates. The download count can be seen as a rough proxy for the number of people who "vouch" for the crate. And finally, asking in chat is always a good idea. [Rust Discord]: https://doc.rust-lang.org/std/fs/struct.File.html#method.try_clone [libs.rs]: https://libs.rs [crates.io]: https://crates.io #### Postpone cleanup until later Like cloning, garbage collection is often frowned upon in Rust — avoiding GC is almost the entire reason Rust exists. But it's no secret that, actually, garbage collection can't be avoided, "garbage collection" and "memory reclaimation" are practically synonymous, and every language uses a mixture of garbage collection strategies. On one end of the GC spectrum, in languages with no automatic memory management, like C, the garbage collection is left entirely up to the programmer, e.g. via `malloc` and `free`. On the other end are garbage collected languages, like Java, where all memory is collected by a single general-purpose garbage collector. In practice though, neither is all memory management and reclaimation in C done with `malloc`/`free`, nor is all memory management in Java done with the GC. Just as a trivial example, it is common for high-performance applications in both to rely on specialized [arenas], in which allocations can both be reused as well as deallocated in large batches, to optimize their memory access patterns. [arenas]: https://www.quora.com/In-C++-what-is-a-memory-arena Likewise in Rust, not all memory is freed deterministically. Trivial examples are in the [`Rc`] and [`Arc`] types that implement [resource counting], a simple kind of GC. [`Rc`]: https://doc.rust-lang.org/std/rc/struct.Rc.html [`Arc`]: https://doc.rust-lang.org/std/sync/struct.Arc.html [reference counting]: https://en.wikipedia.org/wiki/Reference_counting One of the greatest benefits of global garbage collectors is that they make many lock-free data structures possible. Many of the lock-free data structures described in academic literature rely on the GC for their operation. The need to adapt lock-free algorithms to not rely on a GC is the original motivation for the [`crossbeam`] library and its [`epoch`] type. [`crossbeam`]: https://github.com/crossbeam-rs/crossbeam [`epoch`]: https://docs.rs/crossbeam/0.7.1/crossbeam/epoch/index.html All this is to say that garbage collection comes in many forms, and its basic strategy of delaying the cleanup of resources until some future time is powerful in many scenarios. When you can't figure out how to perform some concurrent work _right now_, it can be useful to ask "can I just do this later?" #### Share flags and counters with atomics Under the hood, most concurrent data structures are implemented using [atomic operations], or "atomics". Atomics operate on a single cell of memory, usually between 8 and 128 bytes, commonly word size (the same number of bytes as a pointer, and as the Rust `usize` type). If two threads use atomics correctly then the result of a write in one thread is visible immediately to a read in the other thread. In addition to making reads or writes immediately visible, atomic operations also constrain how the compiler and CPU may reorder instructions, in Rust via the [`Ordering`] flag. [atomic operations]: https://preshing.com/20130618/atomic-vs-non-atomic-operations/ [`atomic`]: https://doc.rust-lang.org/std/sync/atomic/ [`Ordering`]: https://doc.rust-lang.org/std/sync/atomic/enum.Ordering.html When moving from the course-grained parallelism of locks to more fine-grain parallelism, its often necessary to augment off-the-shelf concurrent data structures with atomics. ### Implement lock-free readers That's a lot of background. Hopefully there is a lot there to think about and guide you in the right direction. Now it's your turn: _Modify `KvStore` to perform reads concurrently with writes._ And afterward… Nice coding, friend. Enjoy a nice break. ================================================ FILE: courses/rust/projects/project-4/src/bin/kvs-client.rs ================================================ use clap::AppSettings; use kvs::{KvsClient, Result}; use std::net::SocketAddr; use std::process::exit; use structopt::StructOpt; #[derive(StructOpt, Debug)] #[structopt( name = "kvs-client", raw(global_settings = "&[\ AppSettings::DisableHelpSubcommand,\ AppSettings::VersionlessSubcommands]") )] struct Opt { #[structopt(subcommand)] command: Command, } #[derive(StructOpt, Debug)] enum Command { #[structopt(name = "get", about = "Get the string value of a given string key")] Get { #[structopt(name = "KEY", help = "A string key")] key: String, #[structopt( long, help = "Sets the server address", value_name = "IP:PORT", default_value = "127.0.0.1:4000", parse(try_from_str) )] addr: SocketAddr, }, #[structopt(name = "set", about = "Set the value of a string key to a string")] Set { #[structopt(name = "KEY", help = "A string key")] key: String, #[structopt(name = "VALUE", help = "The string value of the key")] value: String, #[structopt( long, help = "Sets the server address", value_name = "IP:PORT", default_value = "127.0.0.1:4000", parse(try_from_str) )] addr: SocketAddr, }, #[structopt(name = "rm", about = "Remove a given string key")] Remove { #[structopt(name = "KEY", help = "A string key")] key: String, #[structopt( long, help = "Sets the server address", value_name = "IP:PORT", default_value = "127.0.0.1:4000", parse(try_from_str) )] addr: SocketAddr, }, } fn main() { let opt = Opt::from_args(); if let Err(e) = run(opt) { eprintln!("{}", e); exit(1); } } fn run(opt: Opt) -> Result<()> { match opt.command { Command::Get { key, addr } => { let mut client = KvsClient::connect(addr)?; if let Some(value) = client.get(key)? { println!("{}", value); } else { println!("Key not found"); } } Command::Set { key, value, addr } => { let mut client = KvsClient::connect(addr)?; client.set(key, value)?; } Command::Remove { key, addr } => { let mut client = KvsClient::connect(addr)?; client.remove(key)?; } } Ok(()) } ================================================ FILE: courses/rust/projects/project-4/src/bin/kvs-server.rs ================================================ use clap::arg_enum; use kvs::thread_pool::*; use kvs::*; use log::LevelFilter; use log::{error, info, warn}; use std::env; use std::env::current_dir; use std::fs; use std::net::SocketAddr; use std::process::exit; use structopt::StructOpt; const DEFAULT_LISTENING_ADDRESS: &str = "127.0.0.1:4000"; const DEFAULT_ENGINE: Engine = Engine::kvs; #[derive(StructOpt, Debug)] #[structopt(name = "kvs-server")] struct Opt { #[structopt( long, help = "Sets the listening address", value_name = "IP:PORT", raw(default_value = "DEFAULT_LISTENING_ADDRESS"), parse(try_from_str) )] addr: SocketAddr, #[structopt( long, help = "Sets the storage engine", value_name = "ENGINE-NAME", raw(possible_values = "&Engine::variants()") )] engine: Option, } arg_enum! { #[allow(non_camel_case_types)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] enum Engine { kvs, sled } } fn main() { env_logger::builder() .filter_level(LevelFilter::Info) .init(); let mut opt = Opt::from_args(); let res = current_engine().and_then(move |curr_engine| { if opt.engine.is_none() { opt.engine = curr_engine; } if curr_engine.is_some() && opt.engine != curr_engine { error!("Wrong engine!"); exit(1); } run(opt) }); if let Err(e) = res { error!("{}", e); exit(1); } } fn run(opt: Opt) -> Result<()> { let engine = opt.engine.unwrap_or(DEFAULT_ENGINE); info!("kvs-server {}", env!("CARGO_PKG_VERSION")); info!("Storage engine: {}", engine); info!("Listening on {}", opt.addr); // write engine to engine file fs::write(current_dir()?.join("engine"), format!("{}", engine))?; let pool = RayonThreadPool::new(num_cpus::get() as u32)?; match engine { Engine::kvs => run_with(KvStore::open(env::current_dir()?)?, pool, opt.addr), Engine::sled => run_with( SledKvsEngine::new(sled::open(env::current_dir()?)?), pool, opt.addr, ), } } pub fn run_with(engine: E, pool: P, addr: SocketAddr) -> Result<()> { let server = KvsServer::new(engine, pool); server.run(addr) } fn current_engine() -> Result> { let engine = current_dir()?.join("engine"); if !engine.exists() { return Ok(None); } match fs::read_to_string(engine)?.parse() { Ok(engine) => Ok(Some(engine)), Err(e) => { warn!("The content of engine file is invalid: {}", e); Ok(None) } } } ================================================ FILE: courses/rust/projects/project-4/src/client.rs ================================================ use crate::common::{GetResponse, RemoveResponse, Request, SetResponse}; use crate::{KvsError, Result}; use serde::Deserialize; use serde_json::de::{Deserializer, IoRead}; use std::io::{BufReader, BufWriter, Write}; use std::net::{TcpStream, ToSocketAddrs}; /// Key value store client pub struct KvsClient { reader: Deserializer>>, writer: BufWriter, } impl KvsClient { /// Connect to `addr` to access `KvsServer`. pub fn connect(addr: A) -> Result { let tcp_reader = TcpStream::connect(addr)?; let tcp_writer = tcp_reader.try_clone()?; Ok(KvsClient { reader: Deserializer::from_reader(BufReader::new(tcp_reader)), writer: BufWriter::new(tcp_writer), }) } /// Get the value of a given key from the server. pub fn get(&mut self, key: String) -> Result> { serde_json::to_writer(&mut self.writer, &Request::Get { key })?; self.writer.flush()?; let resp = GetResponse::deserialize(&mut self.reader)?; match resp { GetResponse::Ok(value) => Ok(value), GetResponse::Err(msg) => Err(KvsError::StringError(msg)), } } /// Set the value of a string key in the server. pub fn set(&mut self, key: String, value: String) -> Result<()> { serde_json::to_writer(&mut self.writer, &Request::Set { key, value })?; self.writer.flush()?; let resp = SetResponse::deserialize(&mut self.reader)?; match resp { SetResponse::Ok(_) => Ok(()), SetResponse::Err(msg) => Err(KvsError::StringError(msg)), } } /// Remove a string key in the server. pub fn remove(&mut self, key: String) -> Result<()> { serde_json::to_writer(&mut self.writer, &Request::Remove { key })?; self.writer.flush()?; let resp = RemoveResponse::deserialize(&mut self.reader)?; match resp { RemoveResponse::Ok(_) => Ok(()), RemoveResponse::Err(msg) => Err(KvsError::StringError(msg)), } } } ================================================ FILE: courses/rust/projects/project-4/src/common.rs ================================================ use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] pub enum Request { Get { key: String }, Set { key: String, value: String }, Remove { key: String }, } #[derive(Debug, Serialize, Deserialize)] pub enum GetResponse { Ok(Option), Err(String), } #[derive(Debug, Serialize, Deserialize)] pub enum SetResponse { Ok(()), Err(String), } #[derive(Debug, Serialize, Deserialize)] pub enum RemoveResponse { Ok(()), Err(String), } ================================================ FILE: courses/rust/projects/project-4/src/engines/kvs.rs ================================================ use std::cell::RefCell; use std::collections::BTreeMap; use std::ffi::OsStr; use std::fs::{self, File, OpenOptions}; use std::io::{self, BufReader, BufWriter, Read, Seek, SeekFrom, Write}; use std::ops::Range; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::{Arc, Mutex}; use crossbeam_skiplist::SkipMap; use log::error; use serde::{Deserialize, Serialize}; use serde_json::Deserializer; use super::KvsEngine; use crate::{KvsError, Result}; const COMPACTION_THRESHOLD: u64 = 1024 * 1024; /// The `KvStore` stores string key/value pairs. /// /// Key/value pairs are persisted to disk in log files. Log files are named after /// monotonically increasing generation numbers with a `log` extension name. /// A skip list in memory stores the keys and the value locations for fast query. /// /// ```rust /// # use kvs::{KvStore, Result}; /// # fn try_main() -> Result<()> { /// use std::env::current_dir; /// use kvs::KvsEngine; /// let mut store = KvStore::open(current_dir()?)?; /// store.set("key".to_owned(), "value".to_owned())?; /// let val = store.get("key".to_owned())?; /// assert_eq!(val, Some("value".to_owned())); /// # Ok(()) /// # } /// ``` #[derive(Clone)] pub struct KvStore { // directory for the log and other data path: Arc, // map generation number to the file reader index: Arc>, reader: KvStoreReader, writer: Arc>, } impl KvStore { /// Opens a `KvStore` with the given path. /// /// This will create a new directory if the given one does not exist. /// /// # Errors /// /// It propagates I/O or deserialization errors during the log replay. pub fn open(path: impl Into) -> Result { let path = Arc::new(path.into()); fs::create_dir_all(&*path)?; let mut readers = BTreeMap::new(); let index = Arc::new(SkipMap::new()); let gen_list = sorted_gen_list(&path)?; let mut uncompacted = 0; for &gen in &gen_list { let mut reader = BufReaderWithPos::new(File::open(log_path(&path, gen))?)?; uncompacted += load(gen, &mut reader, &*index)?; readers.insert(gen, reader); } let current_gen = gen_list.last().unwrap_or(&0) + 1; let writer = new_log_file(&path, current_gen)?; let safe_point = Arc::new(AtomicU64::new(0)); let reader = KvStoreReader { path: Arc::clone(&path), safe_point, readers: RefCell::new(readers), }; let writer = KvStoreWriter { reader: reader.clone(), writer, current_gen, uncompacted, path: Arc::clone(&path), index: Arc::clone(&index), }; Ok(KvStore { path, reader, index, writer: Arc::new(Mutex::new(writer)), }) } } impl KvsEngine for KvStore { /// Sets the value of a string key to a string. /// /// If the key already exists, the previous value will be overwritten. /// /// # Errors /// /// It propagates I/O or serialization errors during writing the log. fn set(&self, key: String, value: String) -> Result<()> { self.writer.lock().unwrap().set(key, value) } /// Gets the string value of a given string key. /// /// Returns `None` if the given key does not exist. fn get(&self, key: String) -> Result> { if let Some(cmd_pos) = self.index.get(&key) { if let Command::Set { value, .. } = self.reader.read_command(*cmd_pos.value())? { Ok(Some(value)) } else { Err(KvsError::UnexpectedCommandType) } } else { Ok(None) } } /// Removes a given key. /// /// # Error /// /// It returns `KvsError::KeyNotFound` if the given key is not found. /// /// It propagates I/O or serialization errors during writing the log. fn remove(&self, key: String) -> Result<()> { self.writer.lock().unwrap().remove(key) } } /// A single thread reader. /// /// Each `KvStore` instance has its own `KvStoreReader` and /// `KvStoreReader`s open the same files separately. So the user /// can read concurrently through multiple `KvStore`s in different /// threads. struct KvStoreReader { path: Arc, // generation of the latest compaction file safe_point: Arc, readers: RefCell>>, } impl KvStoreReader { /// Close file handles with generation number less than safe_point. /// /// `safe_point` is updated to the latest compaction gen after a compaction finishes. /// The compaction generation contains the sum of all operations before it and the /// in-memory index contains no entries with generation number less than safe_point. /// So we can safely close those file handles and the stale files can be deleted. fn close_stale_handles(&self) { let mut readers = self.readers.borrow_mut(); while !readers.is_empty() { let first_gen = *readers.keys().next().unwrap(); if self.safe_point.load(Ordering::SeqCst) <= first_gen { break; } readers.remove(&first_gen); } } /// Read the log file at the given `CommandPos`. fn read_and(&self, cmd_pos: CommandPos, f: F) -> Result where F: FnOnce(io::Take<&mut BufReaderWithPos>) -> Result, { self.close_stale_handles(); let mut readers = self.readers.borrow_mut(); // Open the file if we haven't opened it in this `KvStoreReader`. // We don't use entry API here because we want the errors to be propogated. if !readers.contains_key(&cmd_pos.gen) { let reader = BufReaderWithPos::new(File::open(log_path(&self.path, cmd_pos.gen))?)?; readers.insert(cmd_pos.gen, reader); } let reader = readers.get_mut(&cmd_pos.gen).unwrap(); reader.seek(SeekFrom::Start(cmd_pos.pos))?; let cmd_reader = reader.take(cmd_pos.len); f(cmd_reader) } // Read the log file at the given `CommandPos` and deserialize it to `Command`. fn read_command(&self, cmd_pos: CommandPos) -> Result { self.read_and(cmd_pos, |cmd_reader| { Ok(serde_json::from_reader(cmd_reader)?) }) } } impl Clone for KvStoreReader { fn clone(&self) -> KvStoreReader { KvStoreReader { path: Arc::clone(&self.path), safe_point: Arc::clone(&self.safe_point), // don't use other KvStoreReader's readers readers: RefCell::new(BTreeMap::new()), } } } struct KvStoreWriter { reader: KvStoreReader, writer: BufWriterWithPos, current_gen: u64, // the number of bytes representing "stale" commands that could be // deleted during a compaction uncompacted: u64, path: Arc, index: Arc>, } impl KvStoreWriter { fn set(&mut self, key: String, value: String) -> Result<()> { let cmd = Command::set(key, value); let pos = self.writer.pos; serde_json::to_writer(&mut self.writer, &cmd)?; self.writer.flush()?; if let Command::Set { key, .. } = cmd { if let Some(old_cmd) = self.index.get(&key) { self.uncompacted += old_cmd.value().len; } self.index .insert(key, (self.current_gen, pos..self.writer.pos).into()); } if self.uncompacted > COMPACTION_THRESHOLD { self.compact()?; } Ok(()) } fn remove(&mut self, key: String) -> Result<()> { if self.index.contains_key(&key) { let cmd = Command::remove(key); let pos = self.writer.pos; serde_json::to_writer(&mut self.writer, &cmd)?; self.writer.flush()?; if let Command::Remove { key } = cmd { let old_cmd = self.index.remove(&key).expect("key not found"); self.uncompacted += old_cmd.value().len; // the "remove" command itself can be deleted in the next compaction // so we add its length to `uncompacted` self.uncompacted += self.writer.pos - pos; } if self.uncompacted > COMPACTION_THRESHOLD { self.compact()?; } Ok(()) } else { Err(KvsError::KeyNotFound) } } /// Clears stale entries in the log. fn compact(&mut self) -> Result<()> { // increase current gen by 2. current_gen + 1 is for the compaction file let compaction_gen = self.current_gen + 1; self.current_gen += 2; self.writer = new_log_file(&self.path, self.current_gen)?; let mut compaction_writer = new_log_file(&self.path, compaction_gen)?; let mut new_pos = 0; // pos in the new log file for entry in self.index.iter() { let len = self.reader.read_and(*entry.value(), |mut entry_reader| { Ok(io::copy(&mut entry_reader, &mut compaction_writer)?) })?; self.index.insert( entry.key().clone(), (compaction_gen, new_pos..new_pos + len).into(), ); new_pos += len; } compaction_writer.flush()?; self.reader .safe_point .store(compaction_gen, Ordering::SeqCst); self.reader.close_stale_handles(); // remove stale log files // Note that actually these files are not deleted immediately because `KvStoreReader`s // still keep open file handles. When `KvStoreReader` is used next time, it will clear // its stale file handles. On Unix, the files will be deleted after all the handles // are closed. On Windows, the deletions below will fail and stale files are expected // to be deleted in the next compaction. let stale_gens = sorted_gen_list(&self.path)? .into_iter() .filter(|&gen| gen < compaction_gen); for stale_gen in stale_gens { let file_path = log_path(&self.path, stale_gen); if let Err(e) = fs::remove_file(&file_path) { error!("{:?} cannot be deleted: {}", file_path, e); } } self.uncompacted = 0; Ok(()) } } /// Create a new log file with given generation number and add the reader to the readers map. /// /// Returns the writer to the log. fn new_log_file(path: &Path, gen: u64) -> Result> { let path = log_path(&path, gen); let writer = BufWriterWithPos::new( OpenOptions::new() .create(true) .write(true) .append(true) .open(&path)?, )?; Ok(writer) } /// Returns sorted generation numbers in the given directory fn sorted_gen_list(path: &Path) -> Result> { let mut gen_list: Vec = fs::read_dir(&path)? .flat_map(|res| -> Result<_> { Ok(res?.path()) }) .filter(|path| path.is_file() && path.extension() == Some("log".as_ref())) .flat_map(|path| { path.file_name() .and_then(OsStr::to_str) .map(|s| s.trim_end_matches(".log")) .map(str::parse::) }) .flatten() .collect(); gen_list.sort_unstable(); Ok(gen_list) } /// Load the whole log file and store value locations in the index map. /// /// Returns how many bytes can be saved after a compaction. fn load( gen: u64, reader: &mut BufReaderWithPos, index: &SkipMap, ) -> Result { // To make sure we read from the beginning of the file let mut pos = reader.seek(SeekFrom::Start(0))?; let mut stream = Deserializer::from_reader(reader).into_iter::(); let mut uncompacted = 0; // number of bytes that can be saved after a compaction while let Some(cmd) = stream.next() { let new_pos = stream.byte_offset() as u64; match cmd? { Command::Set { key, .. } => { if let Some(old_cmd) = index.get(&key) { uncompacted += old_cmd.value().len; } index.insert(key, (gen, pos..new_pos).into()); } Command::Remove { key } => { if let Some(old_cmd) = index.remove(&key) { uncompacted += old_cmd.value().len; } // the "remove" command itself can be deleted in the next compaction // so we add its length to `uncompacted` uncompacted += new_pos - pos; } } pos = new_pos; } Ok(uncompacted) } fn log_path(dir: &Path, gen: u64) -> PathBuf { dir.join(format!("{}.log", gen)) } /// Struct representing a command #[derive(Serialize, Deserialize, Debug)] enum Command { Set { key: String, value: String }, Remove { key: String }, } impl Command { fn set(key: String, value: String) -> Command { Command::Set { key, value } } fn remove(key: String) -> Command { Command::Remove { key } } } /// Represents the position and length of a json-serialized command in the log #[derive(Debug, Clone, Copy)] struct CommandPos { gen: u64, pos: u64, len: u64, } impl From<(u64, Range)> for CommandPos { fn from((gen, range): (u64, Range)) -> Self { CommandPos { gen, pos: range.start, len: range.end - range.start, } } } struct BufReaderWithPos { reader: BufReader, pos: u64, } impl BufReaderWithPos { fn new(mut inner: R) -> Result { let pos = inner.seek(SeekFrom::Current(0))?; Ok(BufReaderWithPos { reader: BufReader::new(inner), pos, }) } } impl Read for BufReaderWithPos { fn read(&mut self, buf: &mut [u8]) -> io::Result { let len = self.reader.read(buf)?; self.pos += len as u64; Ok(len) } } impl Seek for BufReaderWithPos { fn seek(&mut self, pos: SeekFrom) -> io::Result { self.pos = self.reader.seek(pos)?; Ok(self.pos) } } struct BufWriterWithPos { writer: BufWriter, pos: u64, } impl BufWriterWithPos { fn new(mut inner: W) -> Result { let pos = inner.seek(SeekFrom::Current(0))?; Ok(BufWriterWithPos { writer: BufWriter::new(inner), pos, }) } } impl Write for BufWriterWithPos { fn write(&mut self, buf: &[u8]) -> io::Result { let len = self.writer.write(buf)?; self.pos += len as u64; Ok(len) } fn flush(&mut self) -> io::Result<()> { self.writer.flush() } } impl Seek for BufWriterWithPos { fn seek(&mut self, pos: SeekFrom) -> io::Result { self.pos = self.writer.seek(pos)?; Ok(self.pos) } } ================================================ FILE: courses/rust/projects/project-4/src/engines/mod.rs ================================================ pub use self::kvs::KvStore; pub use self::sled::SledKvsEngine; use crate::Result; mod kvs; mod sled; /// Trait for a key value storage engine. pub trait KvsEngine: Clone + Send + 'static { /// Sets the value of a string key to a string. /// /// If the key already exists, the previous value will be overwritten. fn set(&self, key: String, value: String) -> Result<()>; /// Gets the string value of a given string key. /// /// Returns `None` if the given key does not exist. fn get(&self, key: String) -> Result>; /// Removes a given key. /// /// # Errors /// /// It returns `KvsError::KeyNotFound` if the given key is not found. fn remove(&self, key: String) -> Result<()>; } ================================================ FILE: courses/rust/projects/project-4/src/engines/sled.rs ================================================ use super::KvsEngine; use crate::{KvsError, Result}; use sled::{Db, Tree}; /// Wrapper of `sled::Db` #[derive(Clone)] pub struct SledKvsEngine(Db); impl SledKvsEngine { /// Creates a `SledKvsEngine` from `sled::Db`. pub fn new(db: Db) -> Self { SledKvsEngine(db) } } impl KvsEngine for SledKvsEngine { fn set(&self, key: String, value: String) -> Result<()> { let tree: &Tree = &self.0; tree.insert(key, value.into_bytes()).map(|_| ())?; tree.flush()?; Ok(()) } fn get(&self, key: String) -> Result> { let tree: &Tree = &self.0; Ok(tree .get(key)? .map(|i_vec| AsRef::<[u8]>::as_ref(&i_vec).to_vec()) .map(String::from_utf8) .transpose()?) } fn remove(&self, key: String) -> Result<()> { let tree: &Tree = &self.0; tree.remove(key)?.ok_or(KvsError::KeyNotFound)?; tree.flush()?; Ok(()) } } ================================================ FILE: courses/rust/projects/project-4/src/error.rs ================================================ use failure::Fail; use std::io; use std::string::FromUtf8Error; /// Error type for kvs #[derive(Fail, Debug)] pub enum KvsError { /// IO error #[fail(display = "IO error: {}", _0)] Io(#[cause] io::Error), /// Serialization or deserialization error #[fail(display = "serde_json error: {}", _0)] Serde(#[cause] serde_json::Error), /// Removing non-existent key error #[fail(display = "Key not found")] KeyNotFound, /// Unexpected command type error. /// It indicated a corrupted log or a program bug. #[fail(display = "Unexpected command type")] UnexpectedCommandType, /// Key or value is invalid UTF-8 sequence #[fail(display = "UTF-8 error: {}", _0)] Utf8(#[cause] FromUtf8Error), /// Sled error #[fail(display = "sled error: {}", _0)] Sled(#[cause] sled::Error), /// Error with a string message #[fail(display = "{}", _0)] StringError(String), } impl From for KvsError { fn from(err: io::Error) -> KvsError { KvsError::Io(err) } } impl From for KvsError { fn from(err: serde_json::Error) -> KvsError { KvsError::Serde(err) } } impl From for KvsError { fn from(err: FromUtf8Error) -> KvsError { KvsError::Utf8(err) } } impl From for KvsError { fn from(err: sled::Error) -> KvsError { KvsError::Sled(err) } } /// Result type for kvs pub type Result = std::result::Result; ================================================ FILE: courses/rust/projects/project-4/src/lib.rs ================================================ #![deny(missing_docs)] //! A simple key/value store. pub use client::KvsClient; pub use engines::{KvStore, KvsEngine, SledKvsEngine}; pub use error::{KvsError, Result}; pub use server::KvsServer; mod client; mod common; mod engines; mod error; mod server; pub mod thread_pool; ================================================ FILE: courses/rust/projects/project-4/src/server.rs ================================================ use crate::common::{GetResponse, RemoveResponse, Request, SetResponse}; use crate::thread_pool::ThreadPool; use crate::{KvsEngine, Result}; use log::{debug, error}; use serde_json::Deserializer; use std::io::{BufReader, BufWriter, Write}; use std::net::{TcpListener, TcpStream, ToSocketAddrs}; /// The server of a key value store. pub struct KvsServer { engine: E, pool: P, } impl KvsServer { /// Create a `KvsServer` with a given storage engine. pub fn new(engine: E, pool: P) -> Self { KvsServer { engine, pool } } /// Run the server listening on the given address pub fn run(self, addr: A) -> Result<()> { let listener = TcpListener::bind(addr)?; for stream in listener.incoming() { let engine = self.engine.clone(); self.pool.spawn(move || match stream { Ok(stream) => { if let Err(e) = serve(engine, stream) { error!("Error on serving client: {}", e); } } Err(e) => error!("Connection failed: {}", e), }) } Ok(()) } } fn serve(engine: E, tcp: TcpStream) -> Result<()> { let peer_addr = tcp.peer_addr()?; let reader = BufReader::new(&tcp); let mut writer = BufWriter::new(&tcp); let req_reader = Deserializer::from_reader(reader).into_iter::(); macro_rules! send_resp { ($resp:expr) => {{ let resp = $resp; serde_json::to_writer(&mut writer, &resp)?; writer.flush()?; debug!("Response sent to {}: {:?}", peer_addr, resp); };}; } for req in req_reader { let req = req?; debug!("Receive request from {}: {:?}", peer_addr, req); match req { Request::Get { key } => send_resp!(match engine.get(key) { Ok(value) => GetResponse::Ok(value), Err(e) => GetResponse::Err(format!("{}", e)), }), Request::Set { key, value } => send_resp!(match engine.set(key, value) { Ok(_) => SetResponse::Ok(()), Err(e) => SetResponse::Err(format!("{}", e)), }), Request::Remove { key } => send_resp!(match engine.remove(key) { Ok(_) => RemoveResponse::Ok(()), Err(e) => RemoveResponse::Err(format!("{}", e)), }), }; } Ok(()) } ================================================ FILE: courses/rust/projects/project-4/src/thread_pool/mod.rs ================================================ //! This module provides various thread pools. All thread pools should implement //! the `ThreadPool` trait. use crate::Result; mod naive; mod rayon; mod shared_queue; pub use self::naive::NaiveThreadPool; pub use self::rayon::RayonThreadPool; pub use self::shared_queue::SharedQueueThreadPool; /// The trait that all thread pools should implement. pub trait ThreadPool { /// Creates a new thread pool, immediately spawning the specified number of /// threads. /// /// Returns an error if any thread fails to spawn. All previously-spawned threads /// are terminated. fn new(threads: u32) -> Result where Self: Sized; /// Spawns a function into the thread pool. /// /// Spawning always succeeds, but if the function panics the threadpool continues /// to operate with the same number of threads — the thread count is not /// reduced nor is the thread pool destroyed, corrupted or invalidated. fn spawn(&self, job: F) where F: FnOnce() + Send + 'static; } ================================================ FILE: courses/rust/projects/project-4/src/thread_pool/naive.rs ================================================ use std::thread; use super::ThreadPool; use crate::Result; /// It is actually not a thread pool. It spawns a new thread every time /// the `spawn` method is called. pub struct NaiveThreadPool; impl ThreadPool for NaiveThreadPool { fn new(_threads: u32) -> Result { Ok(NaiveThreadPool) } fn spawn(&self, job: F) where F: FnOnce() + Send + 'static, { thread::spawn(job); } } ================================================ FILE: courses/rust/projects/project-4/src/thread_pool/rayon.rs ================================================ use super::ThreadPool; use crate::{KvsError, Result}; /// Wrapper of rayon::ThreadPool pub struct RayonThreadPool(rayon::ThreadPool); impl ThreadPool for RayonThreadPool { fn new(threads: u32) -> Result { let pool = rayon::ThreadPoolBuilder::new() .num_threads(threads as usize) .build() .map_err(|e| KvsError::StringError(format!("{}", e)))?; Ok(RayonThreadPool(pool)) } fn spawn(&self, job: F) where F: FnOnce() + Send + 'static, { self.0.spawn(job) } } ================================================ FILE: courses/rust/projects/project-4/src/thread_pool/shared_queue.rs ================================================ use std::thread; use super::ThreadPool; use crate::Result; use crossbeam::channel::{self, Receiver, Sender}; use log::{debug, error}; // Note for Rust training course: the thread pool is not implemented using // `catch_unwind` because it would require the task to be `UnwindSafe`. /// A thread pool using a shared queue inside. /// /// If a spawned task panics, the old thread will be destroyed and a new one will be /// created. It fails silently when any failure to create the thread at the OS level /// is captured after the thread pool is created. So, the thread number in the pool /// can decrease to zero, then spawning a task to the thread pool will panic. pub struct SharedQueueThreadPool { tx: Sender>, } impl ThreadPool for SharedQueueThreadPool { fn new(threads: u32) -> Result { let (tx, rx) = channel::unbounded::>(); for _ in 0..threads { let rx = TaskReceiver(rx.clone()); thread::Builder::new().spawn(move || run_tasks(rx))?; } Ok(SharedQueueThreadPool { tx }) } /// Spawns a function into the thread pool. /// /// # Panics /// /// Panics if the thread pool has no thread. fn spawn(&self, job: F) where F: FnOnce() + Send + 'static, { self.tx .send(Box::new(job)) .expect("The thread pool has no thread."); } } #[derive(Clone)] struct TaskReceiver(Receiver>); impl Drop for TaskReceiver { fn drop(&mut self) { if thread::panicking() { let rx = self.clone(); if let Err(e) = thread::Builder::new().spawn(move || run_tasks(rx)) { error!("Failed to spawn a thread: {}", e); } } } } fn run_tasks(rx: TaskReceiver) { loop { match rx.0.recv() { Ok(task) => { task(); } Err(_) => debug!("Thread exits because the thread pool is destroyed."), } } } ================================================ FILE: courses/rust/projects/project-4/tests/cli.rs ================================================ use assert_cmd::prelude::*; use predicates::str::{contains, is_empty}; use std::fs::{self, File}; use std::process::Command; use std::sync::mpsc; use std::thread; use std::time::Duration; use tempfile::TempDir; // `kvs-client` with no args should exit with a non-zero code. #[test] fn client_cli_no_args() { let temp_dir = TempDir::new().unwrap(); let mut cmd = Command::cargo_bin("kvs-client").unwrap(); cmd.current_dir(&temp_dir).assert().failure(); } #[test] fn client_cli_invalid_get() { let temp_dir = TempDir::new().unwrap(); Command::cargo_bin("kvs-client") .unwrap() .args(&["get"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "extra", "field"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key", "--addr", "invalid-addr"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key", "--unknown-flag"]) .current_dir(&temp_dir) .assert() .failure(); } #[test] fn client_cli_invalid_set() { let temp_dir = TempDir::new().unwrap(); Command::cargo_bin("kvs-client") .unwrap() .args(&["set"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["set", "missing_field"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["set", "key", "value", "extra_field"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["set", "key", "value", "--addr", "invalid-addr"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key", "--unknown-flag"]) .current_dir(&temp_dir) .assert() .failure(); } #[test] fn client_cli_invalid_rm() { let temp_dir = TempDir::new().unwrap(); Command::cargo_bin("kvs-client") .unwrap() .args(&["rm"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["rm", "extra", "field"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["rm", "key", "--addr", "invalid-addr"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["rm", "key", "--unknown-flag"]) .current_dir(&temp_dir) .assert() .failure(); } #[test] fn client_cli_invalid_subcommand() { let temp_dir = TempDir::new().unwrap(); Command::cargo_bin("kvs-client") .unwrap() .args(&["unknown"]) .current_dir(&temp_dir) .assert() .failure(); } // `kvs-client -V` should print the version #[test] fn client_cli_version() { let temp_dir = TempDir::new().unwrap(); let mut cmd = Command::cargo_bin("kvs-client").unwrap(); cmd.args(&["-V"]) .current_dir(&temp_dir) .assert() .stdout(contains(env!("CARGO_PKG_VERSION"))); } // `kvs-server -V` should print the version #[test] fn server_cli_version() { let temp_dir = TempDir::new().unwrap(); let mut cmd = Command::cargo_bin("kvs-server").unwrap(); cmd.args(&["-V"]) .current_dir(&temp_dir) .assert() .stdout(contains(env!("CARGO_PKG_VERSION"))); } #[test] fn cli_log_configuration() { let temp_dir = TempDir::new().unwrap(); let stderr_path = temp_dir.path().join("stderr"); let mut cmd = Command::cargo_bin("kvs-server").unwrap(); let mut child = cmd .args(&["--engine", "kvs", "--addr", "127.0.0.1:4001"]) .current_dir(&temp_dir) .stderr(File::create(&stderr_path).unwrap()) .spawn() .unwrap(); thread::sleep(Duration::from_secs(1)); child.kill().expect("server exited before killed"); let content = fs::read_to_string(&stderr_path).expect("unable to read from stderr file"); assert!(content.contains(env!("CARGO_PKG_VERSION"))); assert!(content.contains("kvs")); assert!(content.contains("127.0.0.1:4001")); } #[test] fn cli_wrong_engine() { // sled first, kvs second { let temp_dir = TempDir::new().unwrap(); let mut cmd = Command::cargo_bin("kvs-server").unwrap(); let mut child = cmd .args(&["--engine", "sled", "--addr", "127.0.0.1:4002"]) .current_dir(&temp_dir) .spawn() .unwrap(); thread::sleep(Duration::from_secs(1)); child.kill().expect("server exited before killed"); let mut cmd = Command::cargo_bin("kvs-server").unwrap(); cmd.args(&["--engine", "kvs", "--addr", "127.0.0.1:4003"]) .current_dir(&temp_dir) .assert() .failure(); } // kvs first, sled second { let temp_dir = TempDir::new().unwrap(); let mut cmd = Command::cargo_bin("kvs-server").unwrap(); let mut child = cmd .args(&["--engine", "kvs", "--addr", "127.0.0.1:4002"]) .current_dir(&temp_dir) .spawn() .unwrap(); thread::sleep(Duration::from_secs(1)); child.kill().expect("server exited before killed"); let mut cmd = Command::cargo_bin("kvs-server").unwrap(); cmd.args(&["--engine", "sled", "--addr", "127.0.0.1:4003"]) .current_dir(&temp_dir) .assert() .failure(); } } fn cli_access_server(engine: &str, addr: &str) { let (sender, receiver) = mpsc::sync_channel(0); let temp_dir = TempDir::new().unwrap(); let mut server = Command::cargo_bin("kvs-server").unwrap(); let mut child = server .args(&["--engine", engine, "--addr", addr]) .current_dir(&temp_dir) .spawn() .unwrap(); let handle = thread::spawn(move || { let _ = receiver.recv(); // wait for main thread to finish child.kill().expect("server exited before killed"); }); thread::sleep(Duration::from_secs(1)); Command::cargo_bin("kvs-client") .unwrap() .args(&["set", "key1", "value1", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(is_empty()); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key1", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout("value1\n"); Command::cargo_bin("kvs-client") .unwrap() .args(&["set", "key1", "value2", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(is_empty()); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key1", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout("value2\n"); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key2", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(contains("Key not found")); Command::cargo_bin("kvs-client") .unwrap() .args(&["rm", "key2", "--addr", addr]) .current_dir(&temp_dir) .assert() .failure() .stderr(contains("Key not found")); Command::cargo_bin("kvs-client") .unwrap() .args(&["set", "key2", "value3", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(is_empty()); Command::cargo_bin("kvs-client") .unwrap() .args(&["rm", "key1", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(is_empty()); sender.send(()).unwrap(); handle.join().unwrap(); // Reopen and check value let (sender, receiver) = mpsc::sync_channel(0); let mut server = Command::cargo_bin("kvs-server").unwrap(); let mut child = server .args(&["--engine", engine, "--addr", addr]) .current_dir(&temp_dir) .spawn() .unwrap(); let handle = thread::spawn(move || { let _ = receiver.recv(); // wait for main thread to finish child.kill().expect("server exited before killed"); }); thread::sleep(Duration::from_secs(1)); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key2", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(contains("value3")); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key1", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(contains("Key not found")); sender.send(()).unwrap(); handle.join().unwrap(); } #[test] fn cli_access_server_kvs_engine() { cli_access_server("kvs", "127.0.0.1:4004"); } #[test] fn cli_access_server_sled_engine() { cli_access_server("sled", "127.0.0.1:4005"); } ================================================ FILE: courses/rust/projects/project-4/tests/kv_store.rs ================================================ use kvs::{KvStore, KvsEngine, Result}; use std::sync::{Arc, Barrier}; use std::thread; use tempfile::TempDir; use walkdir::WalkDir; // Should get previously stored value #[test] fn get_stored_value() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let store = KvStore::open(temp_dir.path())?; store.set("key1".to_owned(), "value1".to_owned())?; store.set("key2".to_owned(), "value2".to_owned())?; assert_eq!(store.get("key1".to_owned())?, Some("value1".to_owned())); assert_eq!(store.get("key2".to_owned())?, Some("value2".to_owned())); // Open from disk again and check persistent data drop(store); let store = KvStore::open(temp_dir.path())?; assert_eq!(store.get("key1".to_owned())?, Some("value1".to_owned())); assert_eq!(store.get("key2".to_owned())?, Some("value2".to_owned())); Ok(()) } // Should overwrite existent value #[test] fn overwrite_value() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let store = KvStore::open(temp_dir.path())?; store.set("key1".to_owned(), "value1".to_owned())?; assert_eq!(store.get("key1".to_owned())?, Some("value1".to_owned())); store.set("key1".to_owned(), "value2".to_owned())?; assert_eq!(store.get("key1".to_owned())?, Some("value2".to_owned())); // Open from disk again and check persistent data drop(store); let store = KvStore::open(temp_dir.path())?; assert_eq!(store.get("key1".to_owned())?, Some("value2".to_owned())); store.set("key1".to_owned(), "value3".to_owned())?; assert_eq!(store.get("key1".to_owned())?, Some("value3".to_owned())); Ok(()) } // Should get `None` when getting a non-existent key #[test] fn get_non_existent_value() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let store = KvStore::open(temp_dir.path())?; store.set("key1".to_owned(), "value1".to_owned())?; assert_eq!(store.get("key2".to_owned())?, None); // Open from disk again and check persistent data drop(store); let store = KvStore::open(temp_dir.path())?; assert_eq!(store.get("key2".to_owned())?, None); Ok(()) } #[test] fn remove_non_existent_key() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let store = KvStore::open(temp_dir.path())?; assert!(store.remove("key1".to_owned()).is_err()); Ok(()) } #[test] fn remove_key() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let store = KvStore::open(temp_dir.path())?; store.set("key1".to_owned(), "value1".to_owned())?; assert!(store.remove("key1".to_owned()).is_ok()); assert_eq!(store.get("key1".to_owned())?, None); Ok(()) } // Insert data until total size of the directory decreases. // Test data correctness after compaction. #[test] fn compaction() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let store = KvStore::open(temp_dir.path())?; let dir_size = || { let entries = WalkDir::new(temp_dir.path()).into_iter(); let len: walkdir::Result = entries .map(|res| { res.and_then(|entry| entry.metadata()) .map(|metadata| metadata.len()) }) .sum(); len.expect("fail to get directory size") }; let mut current_size = dir_size(); for iter in 0..1000 { for key_id in 0..1000 { let key = format!("key{}", key_id); let value = format!("{}", iter); store.set(key, value)?; } let new_size = dir_size(); if new_size > current_size { current_size = new_size; continue; } // Compaction triggered drop(store); // reopen and check content let store = KvStore::open(temp_dir.path())?; for key_id in 0..1000 { let key = format!("key{}", key_id); assert_eq!(store.get(key)?, Some(format!("{}", iter))); } return Ok(()); } panic!("No compaction detected"); } #[test] fn concurrent_set() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let store = KvStore::open(temp_dir.path())?; let barrier = Arc::new(Barrier::new(1001)); for i in 0..1000 { let store = store.clone(); let barrier = barrier.clone(); thread::spawn(move || { store .set(format!("key{}", i), format!("value{}", i)) .unwrap(); barrier.wait(); }); } barrier.wait(); for i in 0..1000 { assert_eq!(store.get(format!("key{}", i))?, Some(format!("value{}", i))); } // Open from disk again and check persistent data drop(store); let store = KvStore::open(temp_dir.path())?; for i in 0..1000 { assert_eq!(store.get(format!("key{}", i))?, Some(format!("value{}", i))); } Ok(()) } #[test] fn concurrent_get() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let store = KvStore::open(temp_dir.path())?; for i in 0..100 { store .set(format!("key{}", i), format!("value{}", i)) .unwrap(); } let mut handles = Vec::new(); for thread_id in 0..100 { let store = store.clone(); let handle = thread::spawn(move || { for i in 0..100 { let key_id = (i + thread_id) % 100; assert_eq!( store.get(format!("key{}", key_id)).unwrap(), Some(format!("value{}", key_id)) ); } }); handles.push(handle); } for handle in handles { handle.join().unwrap(); } // Open from disk again and check persistent data drop(store); let store = KvStore::open(temp_dir.path())?; let mut handles = Vec::new(); for thread_id in 0..100 { let store = store.clone(); let handle = thread::spawn(move || { for i in 0..100 { let key_id = (i + thread_id) % 100; assert_eq!( store.get(format!("key{}", key_id)).unwrap(), Some(format!("value{}", key_id)) ); } }); handles.push(handle); } for handle in handles { handle.join().unwrap(); } Ok(()) } ================================================ FILE: courses/rust/projects/project-4/tests/thread_pool.rs ================================================ use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use kvs::thread_pool::*; use kvs::Result; use crossbeam_utils::sync::WaitGroup; fn spawn_counter(pool: P) -> Result<()> { const TASK_NUM: usize = 20; const ADD_COUNT: usize = 1000; let wg = WaitGroup::new(); let counter = Arc::new(AtomicUsize::new(0)); for _ in 0..TASK_NUM { let counter = Arc::clone(&counter); let wg = wg.clone(); pool.spawn(move || { for _ in 0..ADD_COUNT { counter.fetch_add(1, Ordering::SeqCst); } drop(wg); }) } wg.wait(); assert_eq!(counter.load(Ordering::SeqCst), TASK_NUM * ADD_COUNT); Ok(()) } fn spawn_panic_task() -> Result<()> { const TASK_NUM: usize = 1000; let pool = P::new(4)?; for _ in 0..TASK_NUM { pool.spawn(move || { // It suppresses flood of panic messages to the console. // You may find it useful to comment this out during development. panic_control::disable_hook_in_current_thread(); panic!(); }) } spawn_counter(pool) } #[test] fn naive_thread_pool_spawn_counter() -> Result<()> { let pool = NaiveThreadPool::new(4)?; spawn_counter(pool) } #[test] fn shared_queue_thread_pool_spawn_counter() -> Result<()> { let pool = SharedQueueThreadPool::new(4)?; spawn_counter(pool) } #[test] fn rayon_thread_pool_spawn_counter() -> Result<()> { let pool = RayonThreadPool::new(4)?; spawn_counter(pool) } #[test] fn shared_queue_thread_pool_panic_task() -> Result<()> { spawn_panic_task::() } ================================================ FILE: courses/rust/projects/project-5/Cargo.toml ================================================ [package] name = "kvs" version = "0.1.0" authors = ["Yilin Chen "] description = "A key-value store" edition = "2018" [dependencies] clap = "2.33.0" structopt = "0.2.15" failure = "0.1.5" serde = { version = "1.0.89", features = ["derive"] } serde_json = "1.0.39" log = "0.4.6" env_logger = "0.6.1" sled = "0.22.1" crossbeam = "0.7.1" rayon = "1.0.3" num_cpus = "1.10.0" crossbeam-skiplist = { version = "0.0.0", git = "https://github.com/crossbeam-rs/crossbeam.git", rev = "8cc906b" } tokio = "0.1.21" tokio-serde-json = "0.2.0" [dev-dependencies] assert_cmd = "0.11" criterion = "0.2.11" crossbeam-utils = "0.6.5" predicates = "1.0.0" rand = "0.6.5" tempfile = "3.0.7" walkdir = "2.2.7" panic-control = "0.1.4" ================================================ FILE: courses/rust/projects/project-5/README.md ================================================ # Project: Asynchrony **Task**: Create a multi-threaded, persistent key/value store server and client with _asynchronous_ networking over a custom protocol. **Goals**: - Understand the patterns used when writing Rust futures - Understand error handling with futures - Learn to debug the type system - Perform asynchronous networking with the tokio runtime - Use boxed futures to handle difficult type-system problems - Use `impl Trait` to create anonymous `Future` types **Topics**: asynchrony, futures, tokio, `impl Trait`. **Extensions**: tokio-fs. - [Introduction](#user-content-introduction) - [Project spec](#user-content-project-spec) - [Project setup](#user-content-project-setup) - [Background: Thinking in futures, in Rust](#user-content-background-thinking-in-futures,-in-rust) - [Part 1: Introducing tokio to the client](#user-content-part-1-introducing-tokio-to-the-client) - [Part 2: Converting `KvsClient` to boxed futures](#user-content-part-2-converting-kvsclient-to-boxed-futures) - [Part 3: `KvsClient` with explicit future types](#user-content-part-3-kvsclient-with-explicit-future-types) - [Part 4: `KvsClient` with anonymous future types](#user-content-part-4-kvsclient-with-anonymous-future-types) - [Part 5: Making `ThreadPool` sharable](#user-content-part-5-making-threadpool-sharable) - [Part 6: Converting `KvsEngine` to futures](#user-content-part-6-converting-kvsengine-to-futures) - [Part 7: Driving `KvsEngine` with tokio](#user-content-part-7-driving-kvsengine-with-tokio) - [Extension 1: Converting to tokio-fs](#user-content-extension-1-converting-to-tokio-fs) ## Introduction _Note: this project is only outlined, not written. If you are at this point in the course email brian@pingcap.com and let me know and I will finish writing it ASAP._ In this project you will create a simple key/value server and client that communicate over a custom protocol. The server will use asynchronous networking, built on the tokio runtime. The key/value engine that reads and writes to files will remain synchronous, scheduling work on an underlying thread pool, while presenting an asynchronous interface. Along the way you will experiment with multiple ways of defining and working with future types. Because learning to program with Rust futures is especially challenging, and existing documentation on the subject is limited, the scope of this project is relatively modest, and it contains more direct explanation than past projects. Be sure to read the background readings on this project. And if you get frustrated, then forgive yourself, take a break, and try again with a fresh mind. Writing asynchronous Rust is difficult for everybody. ## Project spec The cargo project, `kvs`, builds a command-line key-value store client called `kvs-client`, and a key-value store server called `kvs-server`, both of which in turn call into a library called `kvs`. The client speaks to the server over a custom protocol. The interface to the CLI is the same as in the [previous project]. The engine implementation is largely the same, distributing synchronous file I/O over a thread pool. The difference this time is that all the networking is performed asynchronously. As part of the conversion to asynchrony, the `KvsClient` will present a futures-based API, and the `KvsEngine` trait will also present a futures-based API, even while it is implemented with blocking (synchronous) I/O via a thread pool. Your `KvsServer` will be based on the tokio runtime, which handles the distribution of asynchronous work to multiple threads on its own (tokio itself contains a thread pool). This means that your architecture will actually have two layers of thread pools: the first handling with the networking, asynchronously, one thread per core; the second handling the file I/O, synchronously, with enough threads to keep the networking threads as busy as possible. As a result if this architectural change, where your jobs will be spawned into your thread pool from multiple threads, your `ThreadPool` trait and its implementations will become shared types implementing `Clone + Send + 'sync`, as your `KvsEngine` is. Because you will be experimenting with multiple definitions of the futures returned by these types, they aren't fully specified here, and instead will be specified as they are called for. More specifically, you will work with function signatures like all the following: - `Client::get(&mut self, key: String) -> Box, Error = Error>` - `Client::get(&mut self, key: String) -> future::SomeExplicitCombinator<...>` - `Client::get(&mut self, key: String) -> impl Future, Error = Error>` - `Client::get(&mut self, key: String) -> ClientGetFuture` ## Project setup Continuing from your previous project, delete your privous `tests` directory and copy this project's `tests` directory into its place. This project should contain a library named `kvs`, and two executables, `kvs-server` and `kvs-client`. You need the following dev-dependencies in your `Cargo.toml`: ```toml [dev-dependencies] assert_cmd = "0.11" criterion = "0.2.11" crossbeam-utils = "0.6.5" predicates = "1.0.0" rand = "0.6.5" tempfile = "3.0.7" walkdir = "2.2.7" panic-control = "0.1.4" ``` Unlike with previous projects, don't bother to fill in enough type definitions to make the test suite compile. Doing so would require jumping a number of steps ahead at once. The text will indicate when to working with the test suite. ## Background: Thinking in futures, in Rust - why futures? networking vs file/io, blocking vs non-blocking, sync vs async - futures from a user persective (not a poll-centric implementation perspective) - don't think too hard about executors and runtimes - method chaining and how it transforms the future type - debugging Rust types - Result vs Future vs FutureResult - error handling with futures - concrete futures vs boxed futures vs anonymous futures - note about futures 0.1 and futures 0.3 (we'll use futures 0.1) - note about async / await ## Part 1: Introducing tokio to the client Ultimately we're going to convert both the client and server to futures, but since the client is so simple, that's where we'll start. And we're going to introduce the tokio runtime first, while using your existing synchronous `KvsClient`. The for the client we're going to introduce the async runtime while keeping the sync `KvsClient`, then convert the `KvsClient`. The `connect` method of `KvsClient`. note that as a library `KvsClient` can offer the most efficiency based on futures, but our kvs-client bin doesn't take advantage of it, so the bin is going to look a bit silly running a single future and exiting. TODO @sticnarf - see if you can write test cases that are agnostic to the concrete future types, so they work with all the below strategies. ## Part 2: Converting `KvsClient` to boxed futures the path of least resistence for future types ## Part 3: `KvsClient` with explicit future types just to have the experience of seeing how untenable it is ## Part 4: `KvsClient` with anonymous future types the final solution ## Part 5: Making `ThreadPool` sharable ## Part 6: Converting `KvsEngine` to futures for the server we're going to do the opposite of what we did in the client, and give `KvsEngine` an async interface. this will show that futures and the underlying runtime are independent, and just general provide a spectrum of experience. ## Part 7: Driving `KvsEngine` with tokio note that even though we have ourselves have written very little asynchronous code, that tokio itself is distributing asynchronous work across num_cpus threads. think about the tradeoffs of putting cpu-intensive work directly on the network threads or the file threads, e.g. where does the serialization go? TODO Nice coding, friend. Enjoy a nice break. --- ## Extension 1: Converting to tokio-fs not sure if this should be required or an extension ================================================ FILE: courses/rust/projects/project-5/src/bin/kvs-client.rs ================================================ use clap::AppSettings; use kvs::{KvsClient, Result}; use std::net::SocketAddr; use std::process::exit; use structopt::StructOpt; use tokio::prelude::*; #[derive(StructOpt, Debug)] #[structopt( name = "kvs-client", raw(global_settings = "&[\ AppSettings::DisableHelpSubcommand,\ AppSettings::VersionlessSubcommands]") )] struct Opt { #[structopt(subcommand)] command: Command, } #[derive(StructOpt, Debug)] enum Command { #[structopt(name = "get", about = "Get the string value of a given string key")] Get { #[structopt(name = "KEY", help = "A string key")] key: String, #[structopt( long, help = "Sets the server address", value_name = "IP:PORT", default_value = "127.0.0.1:4000", parse(try_from_str) )] addr: SocketAddr, }, #[structopt(name = "set", about = "Set the value of a string key to a string")] Set { #[structopt(name = "KEY", help = "A string key")] key: String, #[structopt(name = "VALUE", help = "The string value of the key")] value: String, #[structopt( long, help = "Sets the server address", value_name = "IP:PORT", default_value = "127.0.0.1:4000", parse(try_from_str) )] addr: SocketAddr, }, #[structopt(name = "rm", about = "Remove a given string key")] Remove { #[structopt(name = "KEY", help = "A string key")] key: String, #[structopt( long, help = "Sets the server address", value_name = "IP:PORT", default_value = "127.0.0.1:4000", parse(try_from_str) )] addr: SocketAddr, }, } fn main() { let opt = Opt::from_args(); if let Err(e) = run(opt) { eprintln!("{}", e); exit(1); } } fn run(opt: Opt) -> Result<()> { match opt.command { Command::Get { key, addr } => { let client = KvsClient::connect(addr); if let (Some(value), _) = client.and_then(move |client| client.get(key)).wait()? { println!("{}", value); } else { println!("Key not found"); } } Command::Set { key, value, addr } => { let client = KvsClient::connect(addr); client .and_then(move |client| client.set(key, value)) .wait()?; } Command::Remove { key, addr } => { let client = KvsClient::connect(addr); client.and_then(move |client| client.remove(key)).wait()?; } } Ok(()) } ================================================ FILE: courses/rust/projects/project-5/src/bin/kvs-server.rs ================================================ #[macro_use] extern crate log; #[macro_use] extern crate clap; use kvs::thread_pool::*; use kvs::{KvStore, KvsEngine, KvsServer, Result, SledKvsEngine}; use log::LevelFilter; use std::env; use std::env::current_dir; use std::fs; use std::net::SocketAddr; use std::process::exit; use structopt::StructOpt; const DEFAULT_LISTENING_ADDRESS: &str = "127.0.0.1:4000"; const DEFAULT_ENGINE: Engine = Engine::kvs; #[derive(StructOpt, Debug)] #[structopt(name = "kvs-server")] struct Opt { #[structopt( long, help = "Sets the listening address", value_name = "IP:PORT", raw(default_value = "DEFAULT_LISTENING_ADDRESS"), parse(try_from_str) )] addr: SocketAddr, #[structopt( long, help = "Sets the storage engine", value_name = "ENGINE-NAME", raw(possible_values = "&Engine::variants()") )] engine: Option, } arg_enum! { #[allow(non_camel_case_types)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] enum Engine { kvs, sled } } fn main() { env_logger::builder().filter_level(LevelFilter::Info).init(); let mut opt = Opt::from_args(); let res = current_engine().and_then(move |curr_engine| { if opt.engine.is_none() { opt.engine = curr_engine; } if curr_engine.is_some() && opt.engine != curr_engine { error!("Wrong engine!"); exit(1); } run(opt) }); if let Err(e) = res { error!("{}", e); exit(1); } } fn run(opt: Opt) -> Result<()> { let engine = opt.engine.unwrap_or(DEFAULT_ENGINE); info!("kvs-server {}", env!("CARGO_PKG_VERSION")); info!("Storage engine: {}", engine); info!("Listening on {}", opt.addr); // write engine to engine file fs::write(current_dir()?.join("engine"), format!("{}", engine))?; let concurrency = num_cpus::get() as u32; match engine { Engine::kvs => run_with( KvStore::::open(env::current_dir()?, concurrency)?, opt.addr, ), Engine::sled => run_with( SledKvsEngine::::new( sled::Db::start_default(env::current_dir()?)?, concurrency, )?, opt.addr, ), } } pub fn run_with(engine: E, addr: SocketAddr) -> Result<()> { let server = KvsServer::new(engine); server.run(addr) } fn current_engine() -> Result> { let engine = current_dir()?.join("engine"); if !engine.exists() { return Ok(None); } match fs::read_to_string(engine)?.parse() { Ok(engine) => Ok(Some(engine)), Err(e) => { warn!("The content of engine file is invalid: {}", e); Ok(None) } } } ================================================ FILE: courses/rust/projects/project-5/src/client.rs ================================================ use crate::common::{Request, Response}; use crate::KvsError; use std::net::SocketAddr; use tokio::codec::{FramedRead, FramedWrite, LengthDelimitedCodec}; use tokio::io::{ReadHalf, WriteHalf}; use tokio::net::TcpStream; use tokio::prelude::*; use tokio_serde_json::{ReadJson, WriteJson}; /// Key value store client pub struct KvsClient { read_json: ReadJson, LengthDelimitedCodec>, Response>, write_json: WriteJson, LengthDelimitedCodec>, Request>, } impl KvsClient { /// Connect to `addr` to access `KvsServer`. pub fn connect(addr: SocketAddr) -> impl Future { TcpStream::connect(&addr) .map(|tcp| { let (read_half, write_half) = tcp.split(); let read_json = ReadJson::new(FramedRead::new(read_half, LengthDelimitedCodec::new())); let write_json = WriteJson::new(FramedWrite::new(write_half, LengthDelimitedCodec::new())); KvsClient { read_json, write_json, } }) .map_err(|e| e.into()) } /// Get the value of a given key from the server. pub fn get(self, key: String) -> impl Future, Self), Error = KvsError> { self.send_request(Request::Get { key }) .and_then(move |(resp, client)| match resp { Some(Response::Get(value)) => Ok((value, client)), Some(Response::Err(msg)) => Err(KvsError::StringError(msg)), Some(_) => Err(KvsError::StringError("Invalid response".to_owned())), None => Err(KvsError::StringError("No response received".to_owned())), }) } /// Set the value of a string key in the server. pub fn set(self, key: String, value: String) -> impl Future { self.send_request(Request::Set { key, value }) .and_then(move |(resp, client)| match resp { Some(Response::Set) => Ok(client), Some(Response::Err(msg)) => Err(KvsError::StringError(msg)), Some(_) => Err(KvsError::StringError("Invalid response".to_owned())), None => Err(KvsError::StringError("No response received".to_owned())), }) } /// Remove a string key in the server. pub fn remove(self, key: String) -> impl Future { self.send_request(Request::Remove { key }) .and_then(move |(resp, client)| match resp { Some(Response::Remove) => Ok(client), Some(Response::Err(msg)) => Err(KvsError::StringError(msg)), Some(_) => Err(KvsError::StringError("Invalid response".to_owned())), None => Err(KvsError::StringError("No response received".to_owned())), }) } fn send_request( self, req: Request, ) -> impl Future, Self), Error = KvsError> { let read_json = self.read_json; self.write_json .send(req) .and_then(move |write_json| { read_json .into_future() .map(move |(resp, read_json)| { let client = KvsClient { read_json, write_json, }; (resp, client) }) .map_err(|(err, _)| err) }) .map_err(|e| e.into()) } } ================================================ FILE: courses/rust/projects/project-5/src/common.rs ================================================ use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] pub enum Request { Get { key: String }, Set { key: String, value: String }, Remove { key: String }, } #[derive(Debug, Serialize, Deserialize)] pub enum Response { Get(Option), Set, Remove, Err(String), } ================================================ FILE: courses/rust/projects/project-5/src/engines/kvs.rs ================================================ use std::cell::RefCell; use std::collections::BTreeMap; use std::ffi::OsStr; use std::fs::{self, File, OpenOptions}; use std::io::{self, BufReader, BufWriter, Read, Seek, SeekFrom, Write}; use std::ops::Range; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicU64, Ordering}; use std::sync::{Arc, Mutex}; use crossbeam::queue::ArrayQueue; use crossbeam_skiplist::SkipMap; use serde::{Deserialize, Serialize}; use serde_json::Deserializer; use tokio::prelude::*; use tokio::sync::oneshot; use super::KvsEngine; use crate::thread_pool::ThreadPool; use crate::{KvsError, Result}; const COMPACTION_THRESHOLD: u64 = 1024 * 1024; /// The `KvStore` stores string key/value pairs. /// /// Key/value pairs are persisted to disk in log files. Log files are named after /// monotonically increasing generation numbers with a `log` extension name. /// A skip list in memory stores the keys and the value locations for fast query. /// /// ```rust /// # use kvs::{KvStore, Result}; /// # use kvs::thread_pool::{ThreadPool, RayonThreadPool}; /// # use tokio::prelude::*; /// # fn try_main() -> Result<()> { /// use std::env::current_dir; /// use kvs::KvsEngine; /// let mut store: KvStore = KvStore::open(current_dir()?, 2)?; /// store.set("key".to_owned(), "value".to_owned()).wait()?; /// let val = store.get("key".to_owned()).wait()?; /// assert_eq!(val, Some("value".to_owned())); /// # Ok(()) /// # } /// ``` #[derive(Clone)] pub struct KvStore { // directory for the log and other data path: Arc, // map generation number to the file reader index: Arc>, writer: Arc>, thread_pool: P, reader_pool: Arc>, } impl KvStore

{ /// Opens a `KvStore` with the given path. /// /// This will create a new directory if the given one does not exist. /// /// `concurrency` specifies how many threads at most can read the database at the same time. /// /// # Errors /// /// It propagates I/O or deserialization errors during the log replay. pub fn open(path: impl Into, concurrency: u32) -> Result { let path = Arc::new(path.into()); fs::create_dir_all(&*path)?; let mut readers = BTreeMap::new(); let index = Arc::new(SkipMap::new()); let gen_list = sorted_gen_list(&path)?; let mut uncompacted = 0; for &gen in &gen_list { let mut reader = BufReaderWithPos::new(File::open(log_path(&path, gen))?)?; uncompacted += load(gen, &mut reader, &*index)?; readers.insert(gen, reader); } let current_gen = gen_list.last().unwrap_or(&0) + 1; let writer = new_log_file(&path, current_gen)?; let safe_point = Arc::new(AtomicU64::new(0)); let reader = KvStoreReader { path: Arc::clone(&path), safe_point, readers: RefCell::new(BTreeMap::new()), }; let writer = KvStoreWriter { reader: reader.clone(), writer, current_gen, uncompacted, path: Arc::clone(&path), index: Arc::clone(&index), }; let thread_pool = P::new(concurrency)?; let reader_pool = Arc::new(ArrayQueue::new(concurrency as usize)); for _ in 1..concurrency { reader_pool.push(reader.clone()).unwrap(); } reader_pool.push(reader).unwrap(); Ok(KvStore { path, index, writer: Arc::new(Mutex::new(writer)), thread_pool, reader_pool, }) } } impl KvsEngine for KvStore

{ /// Sets the value of a string key to a string. /// /// If the key already exists, the previous value will be overwritten. /// /// # Errors /// /// It propagates I/O or serialization errors during writing the log. fn set(&self, key: String, value: String) -> Box + Send> { let writer = self.writer.clone(); let (tx, rx) = oneshot::channel(); self.thread_pool.spawn(move || { let res = writer.lock().unwrap().set(key, value); if tx.send(res).is_err() { error!("Receiving end is dropped"); } }); Box::new( rx.map_err(|e| KvsError::StringError(format!("{}", e))) .flatten(), ) } /// Gets the string value of a given string key. /// /// Returns `None` if the given key does not exist. fn get(&self, key: String) -> Box, Error = KvsError> + Send> { let reader_pool = self.reader_pool.clone(); let index = self.index.clone(); let (tx, rx) = oneshot::channel(); self.thread_pool.spawn(move || { let res = (|| { if let Some(cmd_pos) = index.get(&key) { let reader = reader_pool.pop().unwrap(); let res = if let Command::Set { value, .. } = reader.read_command(*cmd_pos.value())? { Ok(Some(value)) } else { Err(KvsError::UnexpectedCommandType) }; reader_pool.push(reader).unwrap(); res } else { Ok(None) } })(); if tx.send(res).is_err() { error!("Receiving end is dropped"); } }); Box::new( rx.map_err(|e| KvsError::StringError(format!("{}", e))) .flatten(), ) } /// Removes a given key. /// /// # Error /// /// It returns `KvsError::KeyNotFound` if the given key is not found. /// /// It propagates I/O or serialization errors during writing the log. fn remove(&self, key: String) -> Box + Send> { let writer = self.writer.clone(); let (tx, rx) = oneshot::channel(); self.thread_pool.spawn(move || { let res = writer.lock().unwrap().remove(key); if tx.send(res).is_err() { error!("Receiving end is dropped"); } }); Box::new( rx.map_err(|e| KvsError::StringError(format!("{}", e))) .flatten(), ) } } /// A single thread reader. /// /// Each `KvStore` instance has its own `KvStoreReader` and /// `KvStoreReader`s open the same files separately. So the user /// can read concurrently through multiple `KvStore`s in different /// threads. struct KvStoreReader { path: Arc, // generation of the latest compaction file safe_point: Arc, readers: RefCell>>, } impl KvStoreReader { /// Close file handles with generation number less than safe_point. /// /// `safe_point` is updated to the latest compaction gen after a compaction finishes. /// The compaction generation contains the sum of all operations before it and the /// in-memory index contains no entries with generation number less than safe_point. /// So we can safely close those file handles and the stale files can be deleted. fn close_stale_handles(&self) { let mut readers = self.readers.borrow_mut(); while !readers.is_empty() { let first_gen = *readers.keys().next().unwrap(); if self.safe_point.load(Ordering::SeqCst) <= first_gen { break; } readers.remove(&first_gen); } } /// Read the log file at the given `CommandPos`. fn read_and(&self, cmd_pos: CommandPos, f: F) -> Result where F: FnOnce(io::Take<&mut BufReaderWithPos>) -> Result, { self.close_stale_handles(); let mut readers = self.readers.borrow_mut(); // Open the file if we haven't opened it in this `KvStoreReader`. // We don't use entry API here because we want the errors to be propogated. if !readers.contains_key(&cmd_pos.gen) { let reader = BufReaderWithPos::new(File::open(log_path(&self.path, cmd_pos.gen))?)?; readers.insert(cmd_pos.gen, reader); } let reader = readers.get_mut(&cmd_pos.gen).unwrap(); reader.seek(SeekFrom::Start(cmd_pos.pos))?; let cmd_reader = reader.take(cmd_pos.len); f(cmd_reader) } // Read the log file at the given `CommandPos` and deserialize it to `Command`. fn read_command(&self, cmd_pos: CommandPos) -> Result { self.read_and(cmd_pos, |cmd_reader| { Ok(serde_json::from_reader(cmd_reader)?) }) } } impl Clone for KvStoreReader { fn clone(&self) -> KvStoreReader { KvStoreReader { path: Arc::clone(&self.path), safe_point: Arc::clone(&self.safe_point), // don't use other KvStoreReader's readers readers: RefCell::new(BTreeMap::new()), } } } struct KvStoreWriter { reader: KvStoreReader, writer: BufWriterWithPos, current_gen: u64, // the number of bytes representing "stale" commands that could be // deleted during a compaction uncompacted: u64, path: Arc, index: Arc>, } impl KvStoreWriter { fn set(&mut self, key: String, value: String) -> Result<()> { let cmd = Command::set(key, value); let pos = self.writer.pos; serde_json::to_writer(&mut self.writer, &cmd)?; self.writer.flush()?; if let Command::Set { key, .. } = cmd { if let Some(old_cmd) = self.index.get(&key) { self.uncompacted += old_cmd.value().len; } self.index .insert(key, (self.current_gen, pos..self.writer.pos).into()); } if self.uncompacted > COMPACTION_THRESHOLD { self.compact()?; } Ok(()) } fn remove(&mut self, key: String) -> Result<()> { if self.index.contains_key(&key) { let cmd = Command::remove(key); let pos = self.writer.pos; serde_json::to_writer(&mut self.writer, &cmd)?; self.writer.flush()?; if let Command::Remove { key } = cmd { let old_cmd = self.index.remove(&key).expect("key not found"); self.uncompacted += old_cmd.value().len; // the "remove" command itself can be deleted in the next compaction // so we add its length to `uncompacted` self.uncompacted += self.writer.pos - pos; } if self.uncompacted > COMPACTION_THRESHOLD { self.compact()?; } Ok(()) } else { Err(KvsError::KeyNotFound) } } /// Clears stale entries in the log. fn compact(&mut self) -> Result<()> { // increase current gen by 2. current_gen + 1 is for the compaction file let compaction_gen = self.current_gen + 1; self.current_gen += 2; self.writer = new_log_file(&self.path, self.current_gen)?; let mut compaction_writer = new_log_file(&self.path, compaction_gen)?; let mut new_pos = 0; // pos in the new log file for entry in self.index.iter() { let len = self.reader.read_and(*entry.value(), |mut entry_reader| { Ok(io::copy(&mut entry_reader, &mut compaction_writer)?) })?; self.index.insert( entry.key().clone(), (compaction_gen, new_pos..new_pos + len).into(), ); new_pos += len; } compaction_writer.flush()?; self.reader .safe_point .store(compaction_gen, Ordering::SeqCst); self.reader.close_stale_handles(); // remove stale log files // Note that actually these files are not deleted immediately because `KvStoreReader`s // still keep open file handles. When `KvStoreReader` is used next time, it will clear // its stale file handles. On Unix, the files will be deleted after all the handles // are closed. On Windows, the deletions below will fail and stale files are expected // to be deleted in the next compaction. let stale_gens = sorted_gen_list(&self.path)? .into_iter() .filter(|&gen| gen < compaction_gen); for stale_gen in stale_gens { let file_path = log_path(&self.path, stale_gen); if let Err(e) = fs::remove_file(&file_path) { error!("{:?} cannot be deleted: {}", file_path, e); } } self.uncompacted = 0; Ok(()) } } /// Create a new log file with given generation number and add the reader to the readers map. /// /// Returns the writer to the log. fn new_log_file(path: &Path, gen: u64) -> Result> { let path = log_path(&path, gen); let writer = BufWriterWithPos::new( OpenOptions::new() .create(true) .write(true) .append(true) .open(&path)?, )?; Ok(writer) } /// Returns sorted generation numbers in the given directory fn sorted_gen_list(path: &Path) -> Result> { let mut gen_list: Vec = fs::read_dir(&path)? .flat_map(|res| -> Result<_> { Ok(res?.path()) }) .filter(|path| path.is_file() && path.extension() == Some("log".as_ref())) .flat_map(|path| { path.file_name() .and_then(OsStr::to_str) .map(|s| s.trim_end_matches(".log")) .map(str::parse::) }) .flatten() .collect(); gen_list.sort_unstable(); Ok(gen_list) } /// Load the whole log file and store value locations in the index map. /// /// Returns how many bytes can be saved after a compaction. fn load( gen: u64, reader: &mut BufReaderWithPos, index: &SkipMap, ) -> Result { // To make sure we read from the beginning of the file let mut pos = reader.seek(SeekFrom::Start(0))?; let mut stream = Deserializer::from_reader(reader).into_iter::(); let mut uncompacted = 0; // number of bytes that can be saved after a compaction while let Some(cmd) = stream.next() { let new_pos = stream.byte_offset() as u64; match cmd? { Command::Set { key, .. } => { if let Some(old_cmd) = index.get(&key) { uncompacted += old_cmd.value().len; } index.insert(key, (gen, pos..new_pos).into()); } Command::Remove { key } => { if let Some(old_cmd) = index.remove(&key) { uncompacted += old_cmd.value().len; } // the "remove" command itself can be deleted in the next compaction // so we add its length to `uncompacted` uncompacted += new_pos - pos; } } pos = new_pos; } Ok(uncompacted) } fn log_path(dir: &Path, gen: u64) -> PathBuf { dir.join(format!("{}.log", gen)) } /// Struct representing a command #[derive(Serialize, Deserialize, Debug)] enum Command { Set { key: String, value: String }, Remove { key: String }, } impl Command { fn set(key: String, value: String) -> Command { Command::Set { key, value } } fn remove(key: String) -> Command { Command::Remove { key } } } /// Represents the position and length of a json-serialized command in the log #[derive(Debug, Clone, Copy)] struct CommandPos { gen: u64, pos: u64, len: u64, } impl From<(u64, Range)> for CommandPos { fn from((gen, range): (u64, Range)) -> Self { CommandPos { gen, pos: range.start, len: range.end - range.start, } } } struct BufReaderWithPos { reader: BufReader, pos: u64, } impl BufReaderWithPos { fn new(mut inner: R) -> Result { let pos = inner.seek(SeekFrom::Current(0))?; Ok(BufReaderWithPos { reader: BufReader::new(inner), pos, }) } } impl Read for BufReaderWithPos { fn read(&mut self, buf: &mut [u8]) -> io::Result { let len = self.reader.read(buf)?; self.pos += len as u64; Ok(len) } } impl Seek for BufReaderWithPos { fn seek(&mut self, pos: SeekFrom) -> io::Result { self.pos = self.reader.seek(pos)?; Ok(self.pos) } } struct BufWriterWithPos { writer: BufWriter, pos: u64, } impl BufWriterWithPos { fn new(mut inner: W) -> Result { let pos = inner.seek(SeekFrom::Current(0))?; Ok(BufWriterWithPos { writer: BufWriter::new(inner), pos, }) } } impl Write for BufWriterWithPos { fn write(&mut self, buf: &[u8]) -> io::Result { let len = self.writer.write(buf)?; self.pos += len as u64; Ok(len) } fn flush(&mut self) -> io::Result<()> { self.writer.flush() } } impl Seek for BufWriterWithPos { fn seek(&mut self, pos: SeekFrom) -> io::Result { self.pos = self.writer.seek(pos)?; Ok(self.pos) } } ================================================ FILE: courses/rust/projects/project-5/src/engines/mod.rs ================================================ pub use self::kvs::KvStore; pub use self::sled::SledKvsEngine; use crate::KvsError; use tokio::prelude::Future; mod kvs; mod sled; /// Trait for a key value storage engine. pub trait KvsEngine: Clone + Send + 'static { /// Sets the value of a string key to a string. /// /// If the key already exists, the previous value will be overwritten. fn set(&self, key: String, value: String) -> Box + Send>; /// Gets the string value of a given string key. /// /// Returns `None` if the given key does not exist. fn get(&self, key: String) -> Box, Error = KvsError> + Send>; /// Removes a given key. /// /// # Errors /// /// It returns `KvsError::KeyNotFound` if the given key is not found. fn remove(&self, key: String) -> Box + Send>; } ================================================ FILE: courses/rust/projects/project-5/src/engines/sled.rs ================================================ use crate::thread_pool::ThreadPool; use crate::{KvsEngine, KvsError, Result}; use sled::Db; use tokio::prelude::*; use tokio::sync::oneshot; /// Wrapper of `sled::Db` #[derive(Clone)] pub struct SledKvsEngine { pool: P, db: Db, } impl SledKvsEngine

{ /// Creates a `SledKvsEngine` from `sled::Db`. /// /// Operations are run in the given thread pool. `concurrency` specifies the number of /// threads in the thread pool. pub fn new(db: Db, concurrency: u32) -> Result { let pool = P::new(concurrency)?; Ok(SledKvsEngine { pool, db }) } } impl KvsEngine for SledKvsEngine

{ fn set(&self, key: String, value: String) -> Box + Send> { let db = self.db.clone(); let (tx, rx) = oneshot::channel(); self.pool.spawn(move || { let res = db .set(key, value.into_bytes()) .and_then(|_| db.flush()) .map(|_| ()) .map_err(KvsError::from); if tx.send(res).is_err() { error!("Receiving end is dropped"); } }); Box::new( rx.map_err(|e| KvsError::StringError(format!("{}", e))) .flatten(), ) } fn get(&self, key: String) -> Box, Error = KvsError> + Send> { let db = self.db.clone(); let (tx, rx) = oneshot::channel(); self.pool.spawn(move || { let res = (move || { Ok(db .get(key)? .map(|i_vec| AsRef::<[u8]>::as_ref(&i_vec).to_vec()) .map(String::from_utf8) .transpose()?) })(); if tx.send(res).is_err() { error!("Receiving end is dropped"); } }); Box::new( rx.map_err(|e| KvsError::StringError(format!("{}", e))) .flatten(), ) } fn remove(&self, key: String) -> Box + Send> { let db = self.db.clone(); let (tx, rx) = oneshot::channel(); self.pool.spawn(move || { let res = (|| { db.del(key)?.ok_or(KvsError::KeyNotFound)?; db.flush()?; Ok(()) })(); if tx.send(res).is_err() { error!("Receiving end is dropped"); } }); Box::new( rx.map_err(|e| KvsError::StringError(format!("{}", e))) .flatten(), ) } } ================================================ FILE: courses/rust/projects/project-5/src/error.rs ================================================ use failure::Fail; use std::io; use std::string::FromUtf8Error; /// Error type for kvs #[derive(Fail, Debug)] pub enum KvsError { /// IO error #[fail(display = "IO error: {}", _0)] Io(#[cause] io::Error), /// Serialization or deserialization error #[fail(display = "serde_json error: {}", _0)] Serde(#[cause] serde_json::Error), /// Removing non-existent key error #[fail(display = "Key not found")] KeyNotFound, /// Unexpected command type error. /// It indicated a corrupted log or a program bug. #[fail(display = "Unexpected command type")] UnexpectedCommandType, /// Key or value is invalid UTF-8 sequence #[fail(display = "UTF-8 error: {}", _0)] Utf8(#[cause] FromUtf8Error), /// Sled error #[fail(display = "sled error: {}", _0)] Sled(#[cause] sled::Error), /// Error with a string message #[fail(display = "{}", _0)] StringError(String), } impl From for KvsError { fn from(err: io::Error) -> KvsError { KvsError::Io(err) } } impl From for KvsError { fn from(err: serde_json::Error) -> KvsError { KvsError::Serde(err) } } impl From for KvsError { fn from(err: FromUtf8Error) -> KvsError { KvsError::Utf8(err) } } impl From for KvsError { fn from(err: sled::Error) -> KvsError { KvsError::Sled(err) } } /// Result type for kvs pub type Result = std::result::Result; ================================================ FILE: courses/rust/projects/project-5/src/lib.rs ================================================ #![deny(missing_docs)] //! A simple key/value store. #[macro_use] extern crate log; pub use client::KvsClient; pub use engines::{KvStore, KvsEngine, SledKvsEngine}; pub use error::{KvsError, Result}; pub use server::KvsServer; mod client; mod common; mod engines; mod error; mod server; pub mod thread_pool; ================================================ FILE: courses/rust/projects/project-5/src/server.rs ================================================ use crate::common::{Request, Response}; use crate::{KvsEngine, KvsError, Result}; use std::net::SocketAddr; use tokio::codec::{FramedRead, FramedWrite, LengthDelimitedCodec}; use tokio::net::{TcpListener, TcpStream}; use tokio::prelude::*; use tokio_serde_json::{ReadJson, WriteJson}; /// The server of a key value store. pub struct KvsServer { engine: E, } impl KvsServer { /// Create a `KvsServer` with a given storage engine. pub fn new(engine: E) -> Self { KvsServer { engine } } /// Run the server listening on the given address pub fn run(self, addr: SocketAddr) -> Result<()> { let listener = TcpListener::bind(&addr)?; let server = listener .incoming() .map_err(|e| error!("IO error: {}", e)) .for_each(move |tcp| { let engine = self.engine.clone(); serve(engine, tcp).map_err(|e| error!("Error on serving client: {}", e)) }); tokio::run(server); Ok(()) } } fn serve(engine: E, tcp: TcpStream) -> impl Future { let (read_half, write_half) = tcp.split(); let read_json = ReadJson::new(FramedRead::new(read_half, LengthDelimitedCodec::new())); let resp_stream = read_json .map_err(KvsError::from) .and_then( move |req| -> Box + Send> { match req { Request::Get { key } => Box::new(engine.get(key).map(Response::Get)), Request::Set { key, value } => { Box::new(engine.set(key, value).map(|_| Response::Set)) } Request::Remove { key } => { Box::new(engine.remove(key).map(|_| Response::Remove)) } } }, ) .then(|resp| -> Result { match resp { Ok(resp) => Ok(resp), Err(e) => Ok(Response::Err(format!("{}", e))), } }); let write_json = WriteJson::new(FramedWrite::new(write_half, LengthDelimitedCodec::new())); write_json .sink_map_err(KvsError::from) .send_all(resp_stream) .map(|_| ()) } ================================================ FILE: courses/rust/projects/project-5/src/thread_pool/mod.rs ================================================ //! This module provides various thread pools. All thread pools should implement //! the `ThreadPool` trait. use crate::Result; mod naive; mod rayon; mod shared_queue; pub use self::naive::NaiveThreadPool; pub use self::rayon::RayonThreadPool; pub use self::shared_queue::SharedQueueThreadPool; /// The trait that all thread pools should implement. pub trait ThreadPool: Clone + Send + 'static { /// Creates a new thread pool, immediately spawning the specified number of /// threads. /// /// Returns an error if any thread fails to spawn. All previously-spawned threads /// are terminated. fn new(threads: u32) -> Result where Self: Sized; /// Spawns a function into the thread pool. /// /// Spawning always succeeds, but if the function panics the threadpool continues /// to operate with the same number of threads — the thread count is not /// reduced nor is the thread pool destroyed, corrupted or invalidated. fn spawn(&self, job: F) where F: FnOnce() + Send + 'static; } ================================================ FILE: courses/rust/projects/project-5/src/thread_pool/naive.rs ================================================ use std::thread; use super::ThreadPool; use crate::Result; /// It is actually not a thread pool. It spawns a new thread every time /// the `spawn` method is called. #[derive(Clone)] pub struct NaiveThreadPool; impl ThreadPool for NaiveThreadPool { fn new(_threads: u32) -> Result { Ok(NaiveThreadPool) } fn spawn(&self, job: F) where F: FnOnce() + Send + 'static, { thread::spawn(job); } } ================================================ FILE: courses/rust/projects/project-5/src/thread_pool/rayon.rs ================================================ use super::ThreadPool; use crate::{KvsError, Result}; use std::sync::Arc; /// Wrapper of rayon::ThreadPool #[derive(Clone)] pub struct RayonThreadPool(Arc); impl ThreadPool for RayonThreadPool { fn new(threads: u32) -> Result { let pool = rayon::ThreadPoolBuilder::new() .num_threads(threads as usize) .build() .map_err(|e| KvsError::StringError(format!("{}", e)))?; Ok(RayonThreadPool(Arc::new(pool))) } fn spawn(&self, job: F) where F: FnOnce() + Send + 'static, { self.0.spawn(job) } } ================================================ FILE: courses/rust/projects/project-5/src/thread_pool/shared_queue.rs ================================================ use std::thread; use super::ThreadPool; use crate::Result; use crossbeam::channel::{self, Receiver, Sender}; // Note for Rust training course: the thread pool is not implemented using // `catch_unwind` because it would require the task to be `UnwindSafe`. /// A thread pool using a shared queue inside. /// /// If a spawned task panics, the old thread will be destroyed and a new one will be /// created. It fails silently when any failure to create the thread at the OS level /// is captured after the thread pool is created. So, the thread number in the pool /// can decrease to zero, then spawning a task to the thread pool will panic. #[derive(Clone)] pub struct SharedQueueThreadPool { tx: Sender>, } impl ThreadPool for SharedQueueThreadPool { fn new(threads: u32) -> Result { let (tx, rx) = channel::unbounded::>(); for _ in 0..threads { let rx = TaskReceiver(rx.clone()); thread::Builder::new().spawn(move || run_tasks(rx))?; } Ok(SharedQueueThreadPool { tx }) } /// Spawns a function into the thread pool. /// /// # Panics /// /// Panics if the thread pool has no thread. fn spawn(&self, job: F) where F: FnOnce() + Send + 'static, { self.tx .send(Box::new(job)) .expect("The thread pool has no thread."); } } #[derive(Clone)] struct TaskReceiver(Receiver>); impl Drop for TaskReceiver { fn drop(&mut self) { if thread::panicking() { let rx = self.clone(); if let Err(e) = thread::Builder::new().spawn(move || run_tasks(rx)) { error!("Failed to spawn a thread: {}", e); } } } } fn run_tasks(rx: TaskReceiver) { loop { match rx.0.recv() { Ok(task) => { task(); } Err(_) => debug!("Thread exits because the thread pool is destroyed."), } } } ================================================ FILE: courses/rust/projects/project-5/tests/cli.rs ================================================ use assert_cmd::prelude::*; use predicates::str::{contains, is_empty}; use std::fs::{self, File}; use std::process::Command; use std::sync::mpsc; use std::thread; use std::time::Duration; use tempfile::TempDir; // `kvs-client` with no args should exit with a non-zero code. #[test] fn client_cli_no_args() { let temp_dir = TempDir::new().unwrap(); let mut cmd = Command::cargo_bin("kvs-client").unwrap(); cmd.current_dir(&temp_dir).assert().failure(); } #[test] fn client_cli_invalid_get() { let temp_dir = TempDir::new().unwrap(); Command::cargo_bin("kvs-client") .unwrap() .args(&["get"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "extra", "field"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key", "--addr", "invalid-addr"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key", "--unknown-flag"]) .current_dir(&temp_dir) .assert() .failure(); } #[test] fn client_cli_invalid_set() { let temp_dir = TempDir::new().unwrap(); Command::cargo_bin("kvs-client") .unwrap() .args(&["set"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["set", "missing_field"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["set", "key", "value", "extra_field"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["set", "key", "value", "--addr", "invalid-addr"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key", "--unknown-flag"]) .current_dir(&temp_dir) .assert() .failure(); } #[test] fn client_cli_invalid_rm() { let temp_dir = TempDir::new().unwrap(); Command::cargo_bin("kvs-client") .unwrap() .args(&["rm"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["rm", "extra", "field"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["rm", "key", "--addr", "invalid-addr"]) .current_dir(&temp_dir) .assert() .failure(); Command::cargo_bin("kvs-client") .unwrap() .args(&["rm", "key", "--unknown-flag"]) .current_dir(&temp_dir) .assert() .failure(); } #[test] fn client_cli_invalid_subcommand() { let temp_dir = TempDir::new().unwrap(); Command::cargo_bin("kvs-client") .unwrap() .args(&["unknown"]) .current_dir(&temp_dir) .assert() .failure(); } // `kvs-client -V` should print the version #[test] fn client_cli_version() { let temp_dir = TempDir::new().unwrap(); let mut cmd = Command::cargo_bin("kvs-client").unwrap(); cmd.args(&["-V"]) .current_dir(&temp_dir) .assert() .stdout(contains(env!("CARGO_PKG_VERSION"))); } // `kvs-server -V` should print the version #[test] fn server_cli_version() { let temp_dir = TempDir::new().unwrap(); let mut cmd = Command::cargo_bin("kvs-server").unwrap(); cmd.args(&["-V"]) .current_dir(&temp_dir) .assert() .stdout(contains(env!("CARGO_PKG_VERSION"))); } #[test] fn cli_log_configuration() { let temp_dir = TempDir::new().unwrap(); let stderr_path = temp_dir.path().join("stderr"); let mut cmd = Command::cargo_bin("kvs-server").unwrap(); let mut child = cmd .args(&["--engine", "kvs", "--addr", "127.0.0.1:4001"]) .current_dir(&temp_dir) .stderr(File::create(&stderr_path).unwrap()) .spawn() .unwrap(); thread::sleep(Duration::from_secs(1)); child.kill().expect("server exited before killed"); let content = fs::read_to_string(&stderr_path).expect("unable to read from stderr file"); assert!(content.contains(env!("CARGO_PKG_VERSION"))); assert!(content.contains("kvs")); assert!(content.contains("127.0.0.1:4001")); } #[test] fn cli_wrong_engine() { // sled first, kvs second { let temp_dir = TempDir::new().unwrap(); let mut cmd = Command::cargo_bin("kvs-server").unwrap(); let mut child = cmd .args(&["--engine", "sled", "--addr", "127.0.0.1:4002"]) .current_dir(&temp_dir) .spawn() .unwrap(); thread::sleep(Duration::from_secs(1)); child.kill().expect("server exited before killed"); let mut cmd = Command::cargo_bin("kvs-server").unwrap(); cmd.args(&["--engine", "kvs", "--addr", "127.0.0.1:4003"]) .current_dir(&temp_dir) .assert() .failure(); } // kvs first, sled second { let temp_dir = TempDir::new().unwrap(); let mut cmd = Command::cargo_bin("kvs-server").unwrap(); let mut child = cmd .args(&["--engine", "kvs", "--addr", "127.0.0.1:4002"]) .current_dir(&temp_dir) .spawn() .unwrap(); thread::sleep(Duration::from_secs(1)); child.kill().expect("server exited before killed"); let mut cmd = Command::cargo_bin("kvs-server").unwrap(); cmd.args(&["--engine", "sled", "--addr", "127.0.0.1:4003"]) .current_dir(&temp_dir) .assert() .failure(); } } fn cli_access_server(engine: &str, addr: &str) { let (sender, receiver) = mpsc::sync_channel(0); let temp_dir = TempDir::new().unwrap(); let mut server = Command::cargo_bin("kvs-server").unwrap(); let mut child = server .args(&["--engine", engine, "--addr", addr]) .current_dir(&temp_dir) .spawn() .unwrap(); let handle = thread::spawn(move || { let _ = receiver.recv(); // wait for main thread to finish child.kill().expect("server exited before killed"); }); thread::sleep(Duration::from_secs(1)); Command::cargo_bin("kvs-client") .unwrap() .args(&["set", "key1", "value1", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(is_empty()); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key1", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout("value1\n"); Command::cargo_bin("kvs-client") .unwrap() .args(&["set", "key1", "value2", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(is_empty()); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key1", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout("value2\n"); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key2", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(contains("Key not found")); Command::cargo_bin("kvs-client") .unwrap() .args(&["rm", "key2", "--addr", addr]) .current_dir(&temp_dir) .assert() .failure() .stderr(contains("Key not found")); Command::cargo_bin("kvs-client") .unwrap() .args(&["set", "key2", "value3", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(is_empty()); Command::cargo_bin("kvs-client") .unwrap() .args(&["rm", "key1", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(is_empty()); sender.send(()).unwrap(); handle.join().unwrap(); // Reopen and check value let (sender, receiver) = mpsc::sync_channel(0); let mut server = Command::cargo_bin("kvs-server").unwrap(); let mut child = server .args(&["--engine", engine, "--addr", addr]) .current_dir(&temp_dir) .spawn() .unwrap(); let handle = thread::spawn(move || { let _ = receiver.recv(); // wait for main thread to finish child.kill().expect("server exited before killed"); }); thread::sleep(Duration::from_secs(1)); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key2", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(contains("value3")); Command::cargo_bin("kvs-client") .unwrap() .args(&["get", "key1", "--addr", addr]) .current_dir(&temp_dir) .assert() .success() .stdout(contains("Key not found")); sender.send(()).unwrap(); handle.join().unwrap(); } #[test] fn cli_access_server_kvs_engine() { cli_access_server("kvs", "127.0.0.1:4004"); } #[test] fn cli_access_server_sled_engine() { cli_access_server("sled", "127.0.0.1:4005"); } ================================================ FILE: courses/rust/projects/project-5/tests/kv_store.rs ================================================ use kvs::thread_pool::RayonThreadPool; use kvs::{KvStore, KvsEngine, KvsError, Result}; use tempfile::TempDir; use tokio::prelude::*; use tokio::runtime::Runtime; use walkdir::WalkDir; // Should get previously stored value #[test] fn get_stored_value() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let store = KvStore::::open(temp_dir.path(), 1)?; store.set("key1".to_owned(), "value1".to_owned()).wait()?; store.set("key2".to_owned(), "value2".to_owned()).wait()?; assert_eq!( store.get("key1".to_owned()).wait()?, Some("value1".to_owned()) ); assert_eq!( store.get("key2".to_owned()).wait()?, Some("value2".to_owned()) ); // Open from disk again and check persistent data drop(store); let store = KvStore::::open(temp_dir.path(), 1)?; assert_eq!( store.get("key1".to_owned()).wait()?, Some("value1".to_owned()) ); assert_eq!( store.get("key2".to_owned()).wait()?, Some("value2".to_owned()) ); Ok(()) } // Should overwrite existent value #[test] fn overwrite_value() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let store = KvStore::::open(temp_dir.path(), 1)?; store.set("key1".to_owned(), "value1".to_owned()).wait()?; assert_eq!( store.get("key1".to_owned()).wait()?, Some("value1".to_owned()) ); store.set("key1".to_owned(), "value2".to_owned()).wait()?; assert_eq!( store.get("key1".to_owned()).wait()?, Some("value2".to_owned()) ); // Open from disk again and check persistent data drop(store); let store = KvStore::::open(temp_dir.path(), 1)?; assert_eq!( store.get("key1".to_owned()).wait()?, Some("value2".to_owned()) ); store.set("key1".to_owned(), "value3".to_owned()).wait()?; assert_eq!( store.get("key1".to_owned()).wait()?, Some("value3".to_owned()) ); Ok(()) } // Should get `None` when getting a non-existent key #[test] fn get_non_existent_value() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let store = KvStore::::open(temp_dir.path(), 1)?; store.set("key1".to_owned(), "value1".to_owned()).wait()?; assert_eq!(store.get("key2".to_owned()).wait()?, None); // Open from disk again and check persistent data drop(store); let store = KvStore::::open(temp_dir.path(), 1)?; assert_eq!(store.get("key2".to_owned()).wait()?, None); Ok(()) } #[test] fn remove_non_existent_key() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let store = KvStore::::open(temp_dir.path(), 1)?; assert!(store.remove("key1".to_owned()).wait().is_err()); Ok(()) } #[test] fn remove_key() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let store = KvStore::::open(temp_dir.path(), 1)?; store.set("key1".to_owned(), "value1".to_owned()).wait()?; assert!(store.remove("key1".to_owned()).wait().is_ok()); assert_eq!(store.get("key1".to_owned()).wait()?, None); Ok(()) } // Insert data until total size of the directory decreases. // Test data correctness after compaction. #[test] fn compaction() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let store = KvStore::::open(temp_dir.path(), 1)?; let dir_size = || { let entries = WalkDir::new(temp_dir.path()).into_iter(); let len: walkdir::Result = entries .map(|res| { res.and_then(|entry| entry.metadata()) .map(|metadata| metadata.len()) }) .sum(); len.expect("fail to get directory size") }; let mut current_size = dir_size(); for iter in 0..1000 { for key_id in 0..1000 { let key = format!("key{}", key_id); let value = format!("{}", iter); store.set(key, value).wait()?; } let new_size = dir_size(); if new_size > current_size { current_size = new_size; continue; } // Compaction triggered drop(store); // reopen and check content let store = KvStore::::open(temp_dir.path(), 1)?; for key_id in 0..1000 { let key = format!("key{}", key_id); assert_eq!(store.get(key).wait()?, Some(format!("{}", iter))); } return Ok(()); } panic!("No compaction detected"); } #[test] fn concurrent_set() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); // concurrent set in 8 threads let store = KvStore::::open(temp_dir.path(), 8)?; let runtime = Runtime::new()?; let executor = runtime.executor(); runtime.block_on_all(future::lazy(move || { for i in 0..10000 { executor.spawn( store .set(format!("key{}", i), format!("value{}", i)) .map_err(|_| ()), ); } future::ok::<(), KvsError>(()) }))?; // We only check concurrent set in this test, so we check sequentially here let store = KvStore::::open(temp_dir.path(), 1)?; for i in 0..10000 { assert_eq!( store.get(format!("key{}", i)).wait()?, Some(format!("value{}", i)) ); } Ok(()) } #[test] fn concurrent_get() -> Result<()> { let temp_dir = TempDir::new().expect("unable to create temporary working directory"); let store = KvStore::::open(temp_dir.path(), 8)?; // We only check concurrent get in this test, so we set sequentially here for i in 0..100 { store .set(format!("key{}", i), format!("value{}", i)) .wait() .unwrap(); } let runtime = Runtime::new()?; let executor = runtime.executor(); runtime.block_on_all(future::lazy(move || { for thread_id in 0..100 { for i in 0..100 { let key_id = (i + thread_id) % 100; executor.spawn( store .get(format!("key{}", key_id)) .map(move |res| { assert_eq!(res, Some(format!("value{}", key_id))); }) .map_err(|_| ()), ); } } future::ok::<(), KvsError>(()) }))?; // reload from disk and test again let store = KvStore::::open(temp_dir.path(), 8)?; let runtime = Runtime::new()?; let executor = runtime.executor(); runtime.block_on_all(future::lazy(move || { for thread_id in 0..100 { for i in 0..100 { let key_id = (i + thread_id) % 100; executor.spawn( store .get(format!("key{}", key_id)) .map(move |res| { assert_eq!(res, Some(format!("value{}", key_id))); }) .map_err(|_| ()), ); } } future::ok::<(), KvsError>(()) }))?; Ok(()) } ================================================ FILE: courses/rust/projects/project-5/tests/thread_pool.rs ================================================ use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; use kvs::thread_pool::*; use kvs::Result; use crossbeam_utils::sync::WaitGroup; fn spawn_counter(pool: P) -> Result<()> { const TASK_NUM: usize = 20; const ADD_COUNT: usize = 1000; let wg = WaitGroup::new(); let counter = Arc::new(AtomicUsize::new(0)); for _ in 0..TASK_NUM { let counter = Arc::clone(&counter); let wg = wg.clone(); pool.spawn(move || { for _ in 0..ADD_COUNT { counter.fetch_add(1, Ordering::SeqCst); } drop(wg); }) } wg.wait(); assert_eq!(counter.load(Ordering::SeqCst), TASK_NUM * ADD_COUNT); Ok(()) } fn spawn_panic_task() -> Result<()> { const TASK_NUM: usize = 1000; let pool = P::new(4)?; for _ in 0..TASK_NUM { pool.spawn(move || { // It suppresses flood of panic messages to the console. // You may find it useful to comment this out during development. panic_control::disable_hook_in_current_thread(); panic!(); }) } spawn_counter(pool) } #[test] fn naive_thread_pool_spawn_counter() -> Result<()> { let pool = NaiveThreadPool::new(4)?; spawn_counter(pool) } #[test] fn shared_queue_thread_pool_spawn_counter() -> Result<()> { let pool = SharedQueueThreadPool::new(4)?; spawn_counter(pool) } #[test] fn rayon_thread_pool_spawn_counter() -> Result<()> { let pool = RayonThreadPool::new(4)?; spawn_counter(pool) } #[test] fn shared_queue_thread_pool_panic_task() -> Result<()> { spawn_panic_task::() } ================================================ FILE: courses/tp101-intro-to-oss.md ================================================ # TP 101: Introduction to Open Source Software This course includes a collection of some open source software related learning materials and will walk you through some of the key concepts of open source. ***Important note:*** ***Introduction to Open Source Software is in an alpha state.*** Its scope is limited. If you are taking it now you are brave, but you are also an early tester and your feedback is greatly appreciated. You are encouraged to reporting bugs, suggest changes, update the contents, etc. **See [Contributing Guide](../CONTRIBUTING.md)for more details.** ## Who this is for Anyone interesed in open source ## What you will learn? * what open source software is * the history of open source software and what benefits it has provided to the world’s technology infrastructure over the decades * different licensing models that are available, as this will help you decide what the best license is for your project. * open source organizations and the roles of foundations in open source projects ### Prerequisites: None. This course is a great introduction for you to learn open source. ## Course details ### Chapter 1: Open Source Overview **Learning Materials:** * [What is Open Source explained in LEGO](https://www.youtube.com/watch?v=a8fHgx9mE5U), a video made by [Socialsquare](https://www.youtube.com/user/bitblueprint), can help you easily understand the idea of Open Source, even for people with no prior knowledge of Open Source or Free Software. * [6 pivotal moments in open source history](https://opensource.com/article/18/2/pivotal-moments-history-open-source), a blog written by [Dave Neary](https://opensource.com/users/dneary), can help you learn about the key moments in the history of open source. * [Why Open Source](https://ben.balter.com/2015/11/23/why-open-source/), a blog written by [Ben Balter](https://ben.balter.com/about/), listed many reasons why you might consider consuming, publishing, collaborating on, or supporting open source. * [Open Source vs. Closed Source Software](https://www.youtube.com/watch?v=2q91vTvc7YE), a video where you can learn about the differences between open-source software and closed-source software * [The Future of Open Source?](https://www.youtube.com/watch?v=ZCmqeOHhjzk&t=32s) | When Open Source gets monetized, a video talks about what the future of open source looks like. ### Chapter 2: Open Source Licenses **Learning Materials:** * [Licenses & Standards](https://opensource.org/licenses) shows the general accepted licenses, which has undergone rigorous review by the open source legal community. * [Open Source Licenses Comparison [Guide]](https://itsfoss.com/open-source-licenses-explained/) gives an effective Open Source licenses comparison. With Open Source licenses explained there, it should help you choose the right Open Source license for your project. * [The Legal Side of Open Source](https://opensource.guide/legal/) tells everything you've ever wondered about the legal side of open source, and a few things you didn't. ### Chapter 3: Open Source Organizations **Learning Materials:** * [Open source organizations](https://opensource.com/resources/organizations) listed some open source organizations providing processes for managing intellectual property, accepting financial contributions, and other infrastructure and stewardship that growing projects need, such as Apache Software Foundation, Cloud Native Computing Foundation, Linux Foundation, and so on. * [The Role of Foundations in Open Source Projects](https://livablesoftware.com/study-open-source-foundations/), a blog posted by Javier Cánovas, who studied the role of foundations in open source software development with his/her friends, and found that very few foundations are devoted to providing complete support to the projects they endorse, and that their mission is more directed towards providing legal support and leading evangelizing actions. ### Suggeted Assignments You can self-test your learning outcomes by drawing a mindmap of (either of them) : * open source history * pros and cons of open source * how to choose an open source license The mindmap is encourged to be submitted by creating a pull request to the this course. Learn how to create a pull request in [TP 102: How to Use Git and GitHub](tp102-how-to-use-git-github.md) ## Users who took this course also took * [TP 102: How to Use Git and GitHub](tp102-how-to-use-git-github.md) * [TP 103: Build A Welcoming Open Source Community](tp103-open-source-community.md) ## Acknowledgement Special Thanks to `Jamie Xu`, `Lillian Li`, `Ran Huang`, and `Weiwei Wang` for testing this course and updating the materials ================================================ FILE: courses/tp102-how-to-use-git-github.md ================================================ # TP 102: How to Use Git and GitHub Git and GitHub are commonly used tools in open source practice. Whether you are considering contribute to an open source project or start your own open source project. This course includes a collection of Git and GitHub related learning materials and will guide you through everything you need to start contributing, from managing notifications to merging pull requests. ***Important note:*** ***How to Use Git and GitHub is in an alpha state.*** Its scope is limited. If you are taking it now you are brave, but you are also an early tester and your feedback is greatly appreciated. You are encouraged to reporting bugs, suggest changes, update the contents, etc. **See [Contributing Guide](../CONTRIBUTING.md) for more details.** ## Who this is for New GitHub users, users new to Git ## What you will learn? * what GitHub is * how to use GitHub * how to create a branch and a commit * how to review a pull request * how to manage merge conflicts * how to communicate using Markdown ### Prerequisites: None. This course is a great introduction for your first day on GitHub. ## Course details ### Chapter 1: Introduction to GitHub **Learning Material(s):** * [Introduction to GitHub](https://lab.github.com/githubtraining/introduction-to-github), an open source course created by [The GitHub Training Team](https://lab.github.com/githubtraining) **Suggested Assignments:** * Finish the lab. ### Chapter 2: Reviewing pull requests **Learning Material(s):** * [Reviewing pull requests](https://lab.github.com/githubtraining/reviewing-pull-requests), an open source course created by [The GitHub Training Team](https://lab.github.com/githubtraining) **Suggested Assignments:** * Finish the lab. ### Chapter 3: Managing merge conflicts **Learning Material(s):** * [Managing merge conflicts](https://lab.github.com/githubtraining/managing-merge-conflicts), an open source course created by [The GitHub Training Team](https://lab.github.com/githubtraining) **Suggested Assignments:** * Finish the lab. ### Chapter 4: Communicating using Markdown **Learning Material(s):** * [Communicating using Markdown](https://lab.github.com/githubtraining/communicating-using-markdown), an open source course created by [The GitHub Training Team](https://lab.github.com/githubtraining) **Suggested Assignments:** * Finish the lab. ### Chapter 5: Git Handbook * [Git Handbook](https://guides.github.com/introduction/git-handbook/), the official learning material provided by [GitHub Guides](https://guides.github.com/) **Suggested Assignments:** No assignments, the git skill will be tested all the time you participate in an open source project. ## Users who took this course also took * [TP 101: Introduction to Open Source Software](tp101-intro-to-oss.md) * [TP 103: Build A Welcoming Open Source Community](tp103-open-source-community.md) ## Acknowledgement Special Thanks to: * `Producer Wen`, `Qinyao Yang`, and `Jason Zhang`for testing this course and updating the materials. * [The GitHub Training Team](https://lab.github.com/githubtraining) for creating open source courses above. ================================================ FILE: courses/tp103-open-source-community.md ================================================ # TP 103: Build A Welcoming Community A welcoming community is an investment into your project’s future and reputation. People in a welcoming community may be encouraged to use, contribute to, and evangelize your project. This course includes a collection of open source community related learning materials and will guide you through roles in open source projects, community governance model, tips for keeping the community vibrant, combined with open source practice in TiDB as a study case. ***Important note:*** ***Build A Welcoming Community is in an alpha state.*** Its scope is limited. If you are taking it now you are brave, but you are also an early tester and your feedback is greatly appreciated. You are encouraged to reporting bugs, suggest changes, update the contents, etc. **See [Contributing Guide](../CONTRIBUTING.md) for more details.** ## Who this is for Owners of open source projects, open source enthusiasts ## What you will learn? * roles and organism in Open Source Community * community governance model * how to Keep the Community Vibrant * leadership in open source community ### Prerequisites: We recommend you first complete [TP 101: Introduction to Open Source Software](./tp101-intro-to-oss.md) ## Course details ### Chapter 1: Roles and Organism in Open Source Community **Learning Materials:** * [Roles In Open Source Projects](http://oss-watch.ac.uk/resources/rolesinopensource) * [How to build an open source community](http://oss-watch.ac.uk/resources/howtobuildcommunity) * [Governance Models](http://oss-watch.ac.uk/resources/governancemodels) * *[The Cathedral & the Bazaar: Musings on Linux and Open Source by an Accidental Revolutionary](https://www.goodreads.com/book/show/134825.The_Cathedral_the_Bazaar)* ### Chapter 2: Rules for an Online Community **Learning Materials:** * [How to Create & Enforce Rules for an Online Community](https://www.impactbnd.com/blog/how-to-create-enforce-rules-for-an-online-community) * [Writing Great Rules for Your Facebook Group | Facebook Community](https://www.facebook.com/community/establishing-membership-and-rules/how-to-write-great-group-rules/) * [Your Code of Conduct | Open Source Guides](https://opensource.guide/code-of-conduct/) * [GitHub Community Guidelines - GitHub Help](https://help.github.com/en/github/site-policy/github-community-guidelines) * [Women of Email™](https://www.facebook.com/groups/womenofemail/) (Example) * [Community - Kubernetes](https://kubernetes.io/community/code-of-conduct/) (Example) ### Chapter 3: How to Keep the Community Vibrant **Learning Materials:** * Online * [How to Build a Vibrant Open-Source Community in 5 Steps](https://adevait.com/blog/workplace/build-open-source-community) * [25 Experts Drop Wisdom on How to Grow a Vibrant Online Community](https://www.postplanner.com/expert-advice-how-to-grow-vibrant-online-community/) * [How to better communicate with your community](https://www.trainingjournal.com/articles/features/how-better-communicate-your-community) * [How do open source communities blog?](https://mast.informatik.uni-hamburg.de/wp-content/uploads/2013/01/How-do-open-source-communities-blog.pdf) * [The Best 6 Free and Open Source Webinar Software Solutions](https://www.goodfirms.co/blog/best-free-open-source-webinar-software-solutions) * Offline * [Events: The life force of open source](https://www.redhat.com/en/blog/events-life-force-open-source) * [Making the Best Open Source Meetups](https://sourceforge.net/blog/making-best-open-source-meetups/) * [How to Meetup: Hosting and Finding Community Events](https://www.youtube.com/watch?v=SkwKOVCDGM8&list=PLlrxD0HtieHjdA53xa_-iR5KoKHXlVULP&index=23) * [The Top 42 Meetup Open Source Projects](https://awesomeopensource.com/projects/meetup) * [40 top Linux and open source conferences in 2019](https://opensource.com/article/18/12/top-2019-conferences) ### Chapter 4: Leadership in Open Source Community **Learning Materials:** * [How to Community: Anatomy of Successful Open Source Communities and Projects](https://www.youtube.com/watch?v=nGKSnMdBFsk) * [Building effective community leaders: a guide - Jono Bacon at DevXcon 2018](https://www.youtube.com/watch?v=PHHt1I0x8VM) * [Leadership and Governance](https://opensource.guide/leadership-and-governance/) ### Case Study * [Open Source Practice in TiDB](https://github.com/tidb-incubator/tidb-in-action/tree/master/session5) ### Suggested Assignments * Taking an open source project as an example, try to figure out the pros and cons of its community. The outcome is encouraged to be supplemented into [Case Study](#case-study) by creating a pull request. Learn how to create a pull request in [TP 102: How to Use Git and GitHub](tp102-how-to-use-git-github.md). ## Users who took this course also took * [TP 101: Introduction to Open Source Software](tp101-intro-to-oss.md) * [TP 102: How to Use Git and GitHub](tp102-how-to-use-git-github.md) ## Acknowledgement Special Thanks to `Calvin Weng`, `Coco Yi`, `Shen Lin`, `Linda Wang`, `Wenting Liu`, `Yajing Wang`for testing this course and updating the materials. ================================================ FILE: talent-challenge-program/MENTEE_APPLY_TEMPLATE.md ================================================ # Mentee Apply Template Mail to: talent-plan@tidb.io ## Mail Subject: TCP Mentee Application - {project name} - {personal name} ## Message body Please make a self-introduction briefly, including but not limited to: * your name * your nationality * your education background * your performance in talent plan courses or what you have contributed to TiDB projects * the project you are applying for ## Attachments Please attach your updated profile and any other materials that demonstrate your abilities. ================================================ FILE: talent-challenge-program/PROJECT_IDEA_TEMPLATE.md ================================================ ``` #### TiDB Ecosystem Project Name ##### Title - Description: - Recommended Skills: - Mentor(s): - Upstream Issue or RFC (URL): ``` ================================================ FILE: talent-challenge-program/README.md ================================================ # Talent Challenge Program Talent Challenge program is a platform that offers a structured remote mentoring program for **college students** successfully completing talent plan courses or having contributed to TiDB projects. Open source projects related to TiDB ecosystems will be selected together with professional mentors. Students **successfully completing talent plan courses or having contributed to TiDB projects** can apply for the projects, one at a time, and finish the projects with the help of the mentors in a given time. Mentees gain real-world experience by working closely with mentors. Students who successfully complete the projects will receive **bonus and better job opportunities**. ### Current cycle Talent Challenge program season 1 is ongoing, check the timeline and projects available on [dedicated page](s1.md). ## Communication Feel free to contact us in the **#talent-challenge** channel of the [tidbcommunity](https://slack.tidb.io/invite?team=tidb-community&channel=talent-challenge-&ref=github/talent-plan) slack workspace if any questions and suggestions about Talent Challenge program arise. ## How to Participate You can participate in Talent Challenge program based on your role. Talent Challenge supports the following roles. ### Project Maintainers/Mentors Project maintainers or mentors are requested to submit the ideas related to **TiDB Ecosystem** under the [Project Ideas](project-ideas.md) page using the [template](PROJECT_IDEA_TEMPLATE.md). PMC(Project Management Committee) of TiDB community will select the projects that will participate in the Talent Challenge program round and they will appear on the [Selected Projects](selected-projects.md) page after the selection. *Note:* - *Projects to be selected must have one mentor at least.* - *Mentors should be prepared to donate their time to help mentees with the project.* ### Mentees *Note:* - Only **students who have completed talent plan courses or having contributed to TiDB projects** can apply for Talent Challenge program. - You are eligible to participate as a mentee in a single project per-cycle. **Prior to the opening of applications, mentee candidates are encouraged to talk to mentors about the project.** This helps them refine their ideas and deepen their understanding of the project. #### Mentee selection process 1. Mentee candidates who want to participate in Talent Challenge are expected to join Slack Channel ([#talent-challenge](https://slack.tidb.io/invite?team=tidb-community&channel=talent-challenge-&ref=github/talent-plan)) to have self-introductions. 2. The mentors would communicate with mentee candidates about the project they would focus on and assign mentee candidates coding tasks. 3. Mentee candidates need to conduct coding tasks for their desired project under the guidance of mentors and submit their resumes to [talent-plan@tidb.io](maito:talent-plan@tidb.io) using the [template](MENTEE_APPLY_TEMPLATE.md). 4. The mentors would decide whether to accept mentee candidates in the project based on their scores of talent plan courses, coding assignments, and capabilities. ================================================ FILE: talent-challenge-program/project-ideas.md ================================================ ## Project ideas Project maintainers and mentors, please submit the ideas below section using the template. Project ideas selected in season 1 will be listed in [Selected Projects](selected-projects.md) page ### Template ``` #### TiDB Ecosystem Project Name ##### Title - Description: - Recommended Skills: - Mentor(s): - Upstream Issue or RFC (URL): ``` ### Proposed Project ideas #### BR ##### BR HTTP Storage - Description: Support HTTP(S) server as source and destination for BR, and allow BR itself act as an authenticated HTTP(S) server to simplify deployment. - Recommended Skills: Go, Rust, HTTP communication, TLS handling. - Mentor(s): kennytm - Upstream Issue or RFC (URL): - https://github.com/pingcap/br/issues/308, - https://github.com/pingcap/br/issues/212 ##### BR Export - Description: Building on top of BR backup, implement an “export” function to produce CSV and SQL dump. - Recommended Skills: Rust, Go, Row encoding (MVCC and TiDB), gRPC. - Mentor(s): kennytm - Upstream Issue or RFC (URL): https://github.com/pingcap/br/issues/351 #### TiUP Bench ##### Generate BR Backup Archive - Description: Currently TPC-C/TPC-H data prepared by tiup bench can either be inserted via SQL or dumped into CSV files for bulk ingestion. Both methods are slow compared with BR restore. In this project, we want to directly generate a BR backup archive, so benchmarks not caring about the prepare step could be ramped up quickly. - Recommended Skills: Go, Row encoding (TiDB), TiKV/RocksDB SST format - Mentor(s): kennytm - Upstream Issue or RFC (URL): https://github.com/pingcap/go-tpc/issues/46 #### TiCDC ##### TiCDC Cloud Storage - Description: Some usage scenarios need to send the changed events to low-cost storage medium such as S3, in order to keep data for a long time and can consume historical changed events asynchronously. We should design and implement the storage strategy for TiCDC open protocol in cloud storage, and provide the consumption strategies based on the storage sketch in cloud storage. - Recommended Skills: Go, Cloud storage service. - Mentor(s): yangfei Upstream Issue or RFC (URL): https://github.com/pingcap/ticdc/issues/655 ##### TiCDC Snapshot Level Consistency Replication * Description: In many scenarios users want to ensure the downstream is replicated to a globally consistent state, as TiCDC supports eventual transaction consistency, and TiDB supports snapshot read, we could combine these two features and provide a snapshot level consistency replication strategy. * Recommended Skills: Go, Transaction. * Mentor(s): yangfei * Upstream Issue or RFC (URL): https://github.com/pingcap/ticdc/issues/658 ##### TiCDC New Mechanism for ResolvedTS * Description: TiCDC needs a timestamp (called ResolvedTS) in which we can ensure all transactions which start before this timestamp have completed and been sent from TiKV to TiCDC. For now, TiKV must advance the ResolvedTS in the leader of the Raft group. We require a new mechanism to eliminate this restriction. * Recommended Skills: Go, Rust, Raft * Mentor(s): tangminghua * Upstream Issue or RFC (URL): https://github.com/pingcap/ticdc/issues/657 ##### TiCDC Supports Avro Sink and Kafka Connector * Description: Apache Kafka provides a flexible connectors mechanism, which is widely used in change data capture scenarios. We want to implement an Avro sink and make TiCDC compatible with the Kafka connector ecosystem. * Recommended Skills: Go, Kafka. * Mentor(s): yangfei, liuzixiong * Upstream Issue or RFC (URL): https://github.com/pingcap/ticdc/issues/660 ##### TiCDC Support a status mechanism for changefeed * Description: Various errors may be encountered during the execution of replication tasks (e.g. downstream link failure, incompatible DDLs, etc.). we hope to provide a mechanism so that users can quickly understand the status of the current replication task (normal or abnormal), and the reason for the error. * Recommended Skills: Go, SQL. * Mentor(s): zhaoyilin * Upstream Issue or RFC (URL): https://github.com/pingcap/ticdc/issues/664 #### PD ##### PD Store & Region UI * Description: Add display and operation UI for PD stores and regions, in order to reduce the necessity of using pd-ctl and enhance user experience. * Recommended Skills: Go, Web Frontend. * Mentor(s): @HundunDM @breeswish * Upstream Issue or RFC (URL): https://docs.google.com/document/d/1moQVhvIgqu_FWuv_UMB76AM5tETJkyeWnzI04wyevhk/edit ##### PD Encryption at rest * Description: Encryption at rest means that data is encrypted when it is stored, TiKV is already supported, but PD is not. PD stores the meta information of the cluster, especially the Key information of the Region, we need to encrypt it. Here it is proposed that PD also supports encryption. * Recommended Skills: Go, Cryptography * Mentor(s):@yiwu-arbug * Upstream Issue or RFC (URL): * TiKV: https://github.com/tikv/rfcs/blob/929bf1f5d675b555c013d863599544afd9bfe812/text/2020-04-27-encryption-at-rest.md * PD: WIP #### TiDB ##### Live Execution Plan * Description: Provide a way to query current execution details for running SQLs. This feature is similar to the Live Query Statistics in the SQL server. SQL server allows viewing the live execution plan for any queries. * Recommended Skills: Go, SQL * Mentor(s): @crazycs520 @breeswish @qw4990 * Upstream Issue or RFC (URL): https://github.com/pingcap/tidb/issues/17692 ##### Print Txn ID and Query ID in log to trace the whole lifetime of a Txn / SQL * Description: TiDB now outputs TxnStartTs or ConnId in logs, which is not sufficient. This task is to allocate and print a unique TxnId for each transaction, as well as a unique QueryId for each query, for both TiDB and TiKV. * Recommended Skills: Go, Rust * Mentor(s): @crazycs520 @breeswish @SunRunAway * Upstream Issue or RFC (URL): https://github.com/pingcap/tidb/issues/17845 ##### Defining Placement Rules in SQL * Description: TiDB supports placement rules, but it can only be defined in configuration files. If there is an approach to configure placement rules through statements, usability can be improved. * Recommended Skills: Go, Data Definition Language * Mentor(s): @djshow832 * Upstream Issue or RFC (URL): * https://github.com/pingcap/tidb/issues/18030 * https://docs.google.com/document/d/18Kdhi90dv33muF9k_VAIccNLeGf-DdQyUc8JlWF9Gok/edit# ##### Support Multiple Tables Rename in A Statement * Description: TiDB supports renaming one table but doesn’t support renaming multiple tables. This task wants to support renaming multiple tables in a statement. * Recommended Skills: Go, DDL * Mentor(s): @zimulala * Upstream Issue or RFC (URL): https://github.com/pingcap/tidb/issues/14766 ##### Support the operation of dropping multi-indexes in a statement * Description: This task wants to support the operation of dropping multi-indexes in a statement. * Recommended Skills: Go, DDL * Mentor(s): @zimulala * Upstream Issue or RFC (URL): https://github.com/pingcap/tidb/issues/14765 ##### Dropping column with index covered * Description: Support the operation of deleting columns containing indexes. * Recommended Skills: Go, DDL * Mentor(s): @zimulala * Upstream Issue or RFC (URL): https://github.com/pingcap/tidb/issues/3364 ##### Support SAVEPOINT in TiDB * Description: SAVEPOINT is a feature basically supported by mainstream traditional databases (Oracle, DB2, MySQL, and PostgreSQL), and its role is to partially roll back multiple statements of the transaction being executed. TiDB does not currently support this feature. * Recommended Skills: Go * Mentor(s): @bobotu * Upstream Issue or RFC (URL): https://github.com/pingcap/tidb/issues/6840 ##### Support LIST COLUMNS partitioning * Description: LIST COLUMNS partitioning is a feature basically supported by MySQL 8.0, and its role is to define table partition with list columns. TiDB does not currently support this feature. * Recommended Skills: Go, DDL, SQL * Mentor(s): @imtbkcat * Upstream Issue or RFC (URL): https://github.com/pingcap/tidb/issues/18052 ##### Support Global Index for Partition Table * Description: Currently TiDB only supports local partitioned indexes that compatible with mysql,but other database(e.g. Oracle) also supports global partitioned indexes * Recommended Skills: Go, DDL, SQL * Mentor(s): @tiancaiamao * Upstream Issue or RFC (URL): https://github.com/pingcap/tidb/issues/18032 ##### Implement Join Order Hint * Description: Provide a comment style SQL hint to specify the order of joins in the query. * Recommended Skills: Go, SQL * Mentor(s): @eurekaka * Upstream Issue or RFC (URL): WIP ##### Reduce memory consumption of stats data * Description: When there're lots of tables in a TiDB cluster, caching all the stats data into a single TiDB server may cause a high memory consumption when the TiDB server bootstrapped. It increases the OOM risk of the TiDB server. * Recommended Skills: Go * Mentor(s): @SunRunAway * Upstream Issue or RFC (URL): https://github.com/pingcap/tidb/issues/16572 ##### Reduce memory consumption of table meta * Description: TiDB always loads all tables in all schema at once in bootstrap, which can consume very much memory. It increases the OOM risk of the TiDB server. * Recommended Skills: Go * Mentor(s): @bb7133, @SunRunAway * Upstream Issue or RFC (URL): https://github.com/pingcap/tidb/issues/16572 ##### Support utf8_unicode_ci/utf8mb4_unicode_ci collation * Description: Implement the utf8_unicode_ci/utf8mb4_unicode_ci collation algorithm and optimize them. * Recommended Skills: Go * Mentor(s): @wjhuang2016 * Upstream Issue or RFC (URL): https://github.com/pingcap/tidb/issues/17596 ##### Implement More Diagnostics Rules * Description: Add more diagnose rule in TiDB SQL diagnose. * Recommended Skills: Go, SQL * Mentor(s): @crazycs520 * Upstream Issue or RFC (URL): https://github.com/pingcap/tidb/issues/17927 #### TiKV ##### Witness * Description: support raft witness role, and use it in the dual data center deployment scenario, TiDB can still provide service no matter which one of the data center crash * Recommended Skills: Rust, Raft * Mentor(s): @busyjay * Upstream Issue or RFC(URL): WIP ##### Loose Follower Read * Description: Provide a way to read follower doesn’t need to send a request to the leader * Recommended Skills: Rust, Raft * Mentor(s): @hicqu * Upstream Issue or RFC (URL): WIP ##### Write flow control * Description: Control the writing flow by requests' latency, and make the writing smoothly * Recommended Skills: Rust * Mentor(s): @Conner1996 * Upstream Issue or RFC (URL): https://docs.google.com/document/d/1rgm4rS2youwJpy_zpC39BJgxPpnwk7DeuF5LjvWrBZ8/edit# ##### SQL Statement Level Statistics * Description: To make it possible to know what statement is the root cause of hot regions, we need to add local statistics to TiKV that counts top K hot statements and then reports them to PD. * Recommended Skills: Rust, Go * Mentor(s): @breeswish @HundunDM * Upstream Issue or RFC (URL): https://github.com/pingcap-incubator/tidb-dashboard/issues/574 ================================================ FILE: talent-challenge-program/s1.md ================================================ # Talent Challenge Program Season 1 _Status: ongoing_ ### Timeline _Note: this timeline is proposed and may be subject to change before the formal program launch announcement_ - June 7 - June 19: project applications opened - projects are invited to submit their proposals to [Project Ideas](project-ideas.md) page; - June 21: selected projects/slots are announced; - June 21 - July 5: mentees applications opened, projects are selecting mentees; - July 8 - mentees are selected by the mentors, coding starts; - August 5 - 1st evaluation checkpoint; - Mentors verify the quality of the completed tasks; - First 50% of the stipend is being paid to the mentee if this stage is passed; - September 16 - 2nd (final) evaluation checkpoint; - Coding ends; - The other 50% of the stipend is being paid to the mentees; - September 23: results announced! ### Selected Projects Selected projects are listed on the [Selected Projects](selected-projects.md) page ================================================ FILE: talent-challenge-program/selected-projects.md ================================================ ## Selected Projects in Season 1 Selected Projects in Season 1 are listed below. Mentee candidates who want to participate in a certain project please refer to [Mentee Selection Process](README.md#mentees) The difficulty of the project is divided into three levels: Very hard, Hard, and Medium, the corresponding pre-tax bonus is RMB 10000 to a very hard project, RMB 8000 to a hard project and RMB 5000 to a medium project respectively. ### Template ``` #### TiDB Ecosystem Project Name ##### Title - Description: - Recommended Skills: - Mentor(s): - Upstream Issue or RFC (URL): - Difficulty: ``` ## List of Selected Projects #### BR ##### BR Export - Description: Building on top of BR backup, implement an “export” function to produce CSV and SQL dump. - Recommended Skills: Rust, Go, Row encoding (MVCC and TiDB), gRPC. - Mentor(s): @kennytm - Upstream Issue or RFC (URL): https://github.com/pingcap/br/issues/351 - Difficulty: Hard #### TiCDC ##### TiCDC Cloud Storage * Description: Some usage scenarios need to send the changed events to low-cost storage medium such as S3, in order to keep data for a long time and enable consuming historical changed events asynchronously. We should design and implement the storage strategy for TiCDC open protocol in cloud storage, and provide the consumption strategies based on the storage sketch in cloud storage. * Recommended Skills: Go, Cloud storage service. * Mentor(s): @amyangfei * Upstream Issue or RFC (URL): https://github.com/pingcap/ticdc/issues/655 * Difficulty: Medium ##### TiCDC Snapshot Level Consistency Replication * Description: In many scenarios users want to ensure the downstream is replicated to a globally consistent state, as TiCDC supports eventual transaction consistency, and TiDB supports snapshot read, we could combine these two features and provide a snapshot level consistency replication strategy. * Recommended Skills: Go, Transaction. * Mentor(s): @amyangfei * Mentee: [@Colins110](https://github.com/Colins110) * Upstream Issue or RFC (URL): https://github.com/pingcap/ticdc/issues/658 * Difficulty: Medium ##### TiCDC Supports Avro Sink and Kafka Connector * Description: Apache Kafka provides a flexible connectors mechanism, which is widely used in change data capture scenarios. We want to implement an Avro sink and make TiCDC compatible with the Kafka connector ecosystem. * Recommended Skills: Go, Kafka. * Mentor(s): @amyangfei, @liuzx * Mentee: [@qinggniq](https://github.com/qinggniq) * Upstream Issue or RFC (URL): https://github.com/pingcap/ticdc/issues/660 * Difficulty: Medium #### TiDB ##### Live Execution Plan * Description: Provide a way to query current execution details for running SQLs. This feature is similar to the Live Query Statistics in the SQL server. SQL server allows viewing the live execution plan for any queries. * Recommended Skills: Go, SQL * Mentor(s): @crazycs520 @breeswish @qw4990 * Upstream Issue or RFC (URL): https://github.com/pingcap/tidb/issues/17692 * Difficulty: Medium ##### Defining Placement Rules in SQL * Description: TiDB supports placement rules, but it can only be defined in configuration files. If there is an approach to configure placement rules through statements, usability can be improved. * Recommended Skills: Go, Data Definition Language * Mentor(s): @djshow832 * Mentee: [@xhe](https://github.com/xhebox) * Upstream Issue or RFC (URL): https://github.com/pingcap/tidb/issues/18030 * Difficulty: Hard ##### Support SAVEPOINT in TiDB * Description: SAVEPOINT is a feature basically supported by mainstream traditional databases (Oracle, DB2, MySQL, and PostgreSQL), and its role is to partially roll back multiple statements of the transaction being executed. TiDB does not currently support this feature. * Recommended Skills: Go * Mentor(s): @bobotu * Upstream Issue or RFC (URL): https://github.com/pingcap/tidb/issues/6840 * Difficulty: Very Hard ##### Support Global Index for Partition Table * Description: Currently TiDB only supports local partitioned indexes that compatible with mysql,but other database(e.g. Oracle) also supports global partitioned indexes * Recommended Skills: Go, DDL, SQL * Mentor(s): @tiancaiamao * Upstream Issue or RFC (URL): https://github.com/pingcap/tidb/issues/18032 * Difficulty: Hard ##### Reduce memory consumption of stats data * Description: When there're lots of tables in a TiDB cluster, caching all the stats data into a single TiDB server may cause a high memory consumption when the TiDB server bootstrapped. It increases the OOM risk of the TiDB server. * Recommended Skills: Go * Mentor(s): @SunRunAway * Mentee: @[miamiaoxyz](https://github.com/miamia0) * Upstream Issue or RFC (URL): https://github.com/pingcap/tidb/issues/16572 * Difficulty: Medium ##### Support utf8_unicode_ci/utf8mb4_unicode_ci collation * Description: Implement the utf8_unicode_ci/utf8mb4_unicode_ci collation algorithm and optimize them. * Recommended Skills: Go, C++, Rust * Mentor(s): @wjhuang2016 * Mentee: @[xiongjiwei](https://github.com/xiongjiwei) * Upstream Issue or RFC (URL): https://github.com/pingcap/tidb/issues/17596 * Difficulty: Medium #### TiKV ##### SQL Statement Level Statistics * Description: To make it possible to know what statement is the root cause of hot regions, we need to add local statistics to TiKV that counts top K hot statements and then reports them to PD. * Recommended Skills: Rust, Go, Algorithm / Data Structure * Mentor(s): @breeswish @HundunDM * Upstream Issue or RFC (URL): https://github.com/pingcap-incubator/tidb-dashboard/issues/574 * Difficulty: Hard ##### HBase protocol support on Zetta * Description: Zetta is designed as a BigTable implementation on top of TiKV to support structured schemaless data model. In order to elaborate existing HBase ecosystem, we plan to implement the HBase protocol adaptor for Zetta. To achieve this, we need to: 1. Implement a mock ZooKeeper to eliminate external dependency 2. Implement RPC protocol of HBase RegionServer 3. Implement HBase functionality on top of Zetta * Recommended Skills: Go, Java, HBase RPC * Mentor(s): pseudocodes, baiyuqing * Mentee: [@BowenXiao1999](https://github.com/BowenXiao1999) * Upstream Issue or RFC (URL): https://github.com/zhihu/zetta/issues/2(in Chinese) * Difficulty: Hard #### Chaos Mesh ##### Support using plugins to extend scheduler * Description: In many scenarios users need to customize selector. For example, when our tidb cluster has multiple pds, we just want to inject the failure to the leader. So we need to provide a plugin to let the users to extend the selector, and users can implement their own selector through code. For example, we can create a file called `pd-selector.go` and set it in the selector field. * Recommended Skills: Go, Kubernetes * Mentor(s): @cwen0 * Upstream Issue or RFC (URL): https://github.com/pingcap/chaos-mesh/issues/193 * Difficulty: Medium ##### Support injecting HTTP fault * Description: In many scenarios, users need to inject an HTTP delay fault or an HTTP abort fault on the special application. For example, we just want to inject a delay fault on getting `/api/xxx` router. * Recommended Skills: Go, Kuberenetes * Mentor(s): @Yisaer * Upstream Issue or RFC (URL): https://github.com/pingcap/chaos-mesh/issues/651 * Difficulty: Hard ================================================ FILE: talent-challenge-program2021/MENTEE_APPLY_TEMPLATE.md ================================================ # Mentee Application Form Template Mail to: talent-plan@tidb.io ## Mail Subject: TCP Mentee Application - {project name} - {personal name} ## Message body Please make a self-introduction briefly, including but not limited to: * Your name * Your nationality * Your education background * The project you are applying for * Your performance in talent plan courses or what you have contributed to TiDB projects * Any other evidences that prove your capabilities ## Attachments Please attach your updated profile and any other materials that demonstrate your abilities. ================================================ FILE: talent-challenge-program2021/PROJECT_IDEA_TEMPLATE.md ================================================ ``` ## Description what's the problem, how to solve it ## Document Collection - Proposal doc: ${proposal doc} - Weekly report: ${weekly report link} ## Talent Challenge Program information - Mentor of this issue: @github_id - Recommended skills: ${skills and URL link} - Estimated Workloads: (XL, man-month) ## Milestones and action items Milestone 1: ${milestone descption}, Expected finish date: ${date} - [ ] action item 1 - [ ] action item 2 Milestone 2: ${milestone descption}, Expected finish date: ${date} - [ ] action item 1 - [ ] action item 2 ``` ================================================ FILE: talent-challenge-program2021/README.md ================================================ # Talent Challenge Program 2021 Talent Challenge program is a platform that offers a structured remote mentoring program for **college students** who have successfully completed talent plan courses or contributed to TiDB projects. Open source projects related to TiDB ecosystems will be selected together with professional mentors. Students can apply for the projects, one at a time, and finish the projects with the help of the mentors in a given time. Mentees gain real-world experiences by working closely with mentors. Students who successfully complete the projects will receive **bonus and better job opportunities**. ### Current cycle Talent Challenge program 2021 is ongoing, check the timeline and projects available on [dedicated page](schedule.md). ## Communication Feel free to contact us in the **#talent-challenge** channel of the [tidbcommunity](https://slack.tidb.io/invite?team=tidb-community&channel=talent-challenge-&ref=github/talent-plan) slack workspace if any questions and suggestions about Talent Challenge program arise. ## How to Participate You can participate in Talent Challenge program based on your role. Talent Challenge supports the following roles. ### Project Maintainers/Mentors Project maintainers or mentors are requested to submit the ideas related to **TiDB Ecosystem** under the [Project Ideas](project-ideas.md) page using the [template](PROJECT_IDEA_TEMPLATE.md). PMC(Project Management Committee) of TiDB community will select the projects that will participate in the Talent Challenge program round and they will appear on the [Selected Projects](selected-projects.md) page after the selection. *Note:* - *Projects to be selected must have one mentor at least.* - *Mentors should be prepared to donate their time to help mentees with the project.* ### Mentees *Note:* - Must be college students at school. - **Students who have completed talent plan courses or contributed to TiDB projects** are encouraged to apply for the program and they will be considered as priority, or who have proven capabilites on distributed database development. - You are eligible to participate as a mentee in a single project per-cycle. **Prior to the opening of applications, mentee candidates are encouraged to talk to mentors about the project.** This helps them refine their ideas and deepen their understanding of the project. #### Mentee selection process 1. Mentee candidates who want to participate in Talent Challenge are expected to join Slack Channel ([#talent-challenge](https://slack.tidb.io/invite?team=tidb-community&channel=talent-challenge-&ref=github/talent-plan)) to have self-introductions. 2. The mentors would communicate with mentee candidates about the project they would focus on and assign mentee candidates coding tasks. 3. Mentee candidates need to conduct coding tasks for their desired project under the guidance of mentors and submit their resumes to [talent-plan@tidb.io](maito:talent-plan@tidb.io) using the [template](MENTEE_APPLY_TEMPLATE.md). 4. The mentors would decide whether to accept mentee candidates in the project based on their scores of talent plan courses, coding assignments, and capabilities. ================================================ FILE: talent-challenge-program2021/project-ideas.md ================================================ ## Project ideas Project maintainers and mentors, please submit the ideas below section using the template. Project ideas selected in season 1 will be listed in [Selected Projects](selected-projects.md) page ### Template ``` ## TiDB Ecosystem Project Name ## Title ## Description what's the problem, how to solve it ## Document Collection - Proposal doc: ${proposal doc} - Weekly report: ${weekly report link} ## Talent Challenge Program information - Mentor of this issue: @github_id - Recommended skills: ${skills and URL link} - Estimated Workloads: (XL, man-month) ## Milestones and action items Milestone 1: ${milestone descption}, Expected finish date: ${date} - [ ] action item 1 - [ ] action item 2 Milestone 2: ${milestone descption}, Expected finish date: ${date} - [ ] action item 1 - [ ] action item 2 ``` ### Proposed Project ideas ================================================ FILE: talent-challenge-program2021/schedule.md ================================================ # Talent Challenge Program 2021 Schedule _Status: ongoing_ ### Timeline _Note: this timeline is proposed and may be subject to change before the formal program launch announcement_ #### Season 1 - June 15 - July 15: mentees applications opened, projects are selecting mentees; - July 19 - mentees are selected by the mentors, coding starts; - 1st evaluation checkpoint (mentor decides); - Mentors verify the quality of the completed tasks; - First 50% of the stipend is being paid to the mentee if this stage is passed; - 2nd (final) evaluation checkpoint (mentor decides); - Coding ends; - The other 50% of the stipend is being paid to the mentees; - results announced! #### Season 2 - Sep 01 - Sep 15: mentees applications opened, projects are selecting mentees; - Sep 20 - mentees are selected by the mentors, coding starts; - 1st evaluation checkpoint (mentor decides); - Mentors verify the quality of the completed tasks; - First 50% of the stipend is being paid to the mentee if this stage is passed; - 2nd (final) evaluation checkpoint (mentor decides); - Coding ends; - The other 50% of the stipend is being paid to the mentees; - results announced! #### Season 3 - Nov 01 - Nov 15: mentees applications opened, projects are selecting mentees; - Nov 18 - mentees are selected by the mentors, coding starts; - 1st evaluation checkpoint (mentor decides); - Mentors verify the quality of the completed tasks; - First 50% of the stipend is being paid to the mentee if this stage is passed; - 2nd (final) evaluation checkpoint (mentor decides); - Coding ends; - The other 50% of the stipend is being paid to the mentees; - results announced! ### Selected Projects Selected projects are listed on the [Selected Projects](selected-projects.md) page ================================================ FILE: talent-challenge-program2021/selected-projects.md ================================================ ## Selected Projects in Season 1 Selected Projects in Sprint 1 are listed below. Mentee candidates who want to participate in a certain project please refer to [Mentee Selection Process](README.md#mentees) The difficulty of the project is divided into three levels: Very hard, Hard, and Medium, the corresponding pre-tax bonus is RMB 10000 to a very hard project, RMB 8000 to a hard project and RMB 5000 to a medium project respectively. ### Template ``` ## Description what's the problem, how to solve it ## Document Collection - Proposal doc: ${proposal doc} - Weekly report: ${weekly report link} ## Talent Challenge Program information - Mentor of this issue: @github_id - Recommended skills: ${skills and URL link} - Estimated Workloads: (XL, man-month) ## Milestones and action items Milestone 1: ${milestone descption}, Expected finish date: ${date} - [ ] action item 1 - [ ] action item 2 Milestone 2: ${milestone descption}, Expected finish date: ${date} - [ ] action item 1 - [ ] action item 2 ``` ## List of Selected Projects #### SQL * [tidb/issues/25149](https://github.com/pingcap/tidb/issues/25149) Optimize CTE performance, [@wjhuang2016](https://github.com/wjhuang2016) * [tidb/issues/14486](https://github.com/pingcap/tidb/issues/14486) (Occupied)Implement missing JSON functions, [@nullnotnil](https://github.com/nullnotnil) * [tidb/issues/25152](https://github.com/pingcap/tidb/issues/25152) GBK charset, [@xiongjiwei](https://github.com/xiongjiwei) * [tidb/issues/25150](https://github.com/pingcap/tidb/issues/25150) (Occupied)Expression index GA, [@wjhuang2016](https://github.com/wjhuang2016) * [tidb/issues/25204](https://github.com/pingcap/tidb/issues/25204) Local temporary table, [@djshow832](https://github.com/djshow832) * [tidb/issues/14580](https://github.com/pingcap/tidb/issues/14580) Only full group by check,needed things(relational algebra, graph theory), [@winoros](https://github.com/winoros) * [tidb/issues/25293](https://github.com/pingcap/tidb/issues/25293) (Occupied)Optimizing hotspot small tables, [@tiancaiamao](https://github.com/tiancaiamao) * [tidb/issues/13709](https://github.com/pingcap/tidb/issues/13709) (Occupied)Cascades planner,[@chrysanxia](https://github.com/chrysanxia) * [tidb/issues/18745](https://github.com/pingcap/tidb/issues/18745) (Occupied)Support to export historical statistics,[@qw4990](https://github.com/qw4990) #### Storage * [tidb/issues/25281](https://github.com/pingcap/tidb/issues/25281) (Occupied)Historical Hotspot Region, [@nolouch](https://github.com/nolouch) * [pd/issues/4095](https://github.com/tikv/pd/issues/4095)(Occupied)Enhance Split Table Stability and Usability,[@Yisaer](https://github.com/Yisaer) * [pd/issues/3736](https://github.com/tikv/pd/issues/3736) Build scheduling model with Simulink, [@bufferflies](https://github.com/bufferflies) * [tikv/issues/10867](https://github.com/tikv/tikv/issues/10867) (Occupied)Support limiting read flow for TiKV IO rate limiter,[@Connor1996](https://github.com/connor1996) #### Talent Plan * [tidb/issues/25321](https://github.com/pingcap/tidb/issues/25321)(Occupied) TinySQL: design and implement a learning-friendly distributed database [@rebelice](https://github.com/rebelice) ================================================ FILE: talent-plan-1.0/1.0-lp-tidb.md ================================================ # 路径 1:TiDB 方向 ## 课程目标 * 掌握 Go 语言 * 掌握分布式计算基本原理 * 掌握数据库基础知识 * 掌握优化器和执行引擎基本原理 ## 课程内容 ### Section 1 熟悉 Go 语言基础知识 **学习资料:** * 阅读许老师的书 [《Go 语言开发》](https://book.douban.com/subject/11577300/) * [Go 官方教程](http://tour.golang.org/) * [Effective Go](https://golang.org/doc/effective_go.html) * [Profiling Go Programs](https://blog.golang.org/profiling-go-programs) **课程作业:** * 用 Go 语言实现一个多路归并的 Merge Sort:内存中有一个无序的 int64 数组,数组中有 16M 个整数,要求使用多个 goroutine 对这个无序数组进行排序,使得有元素按照从小到大的顺序排列,并且排序的性能需要比单线程 Quick Sort 快。 * 根据[框架](https://github.com/pingcap/talent-plan/tree/master/tidb/mergesort)完成程序,**要求跑通测试程序,并使用 Go Profile 工具分析性能瓶颈。需要有文档、单元测试、性能瓶颈分析。** ### Section 2 分布式计算基础知识 **学习资料:** * 学习并使用 Go 语言完成 [6.824 Lab 1: MapReduce](https://pdos.csail.mit.edu/6.824/labs/lab-1.html) **课程作业:** * 使用 Go 语言,使用框架代码,用 MapReduce + Shuffle 的方式完成作业:从包含大量 URL 的数据文件中,求出现次数最多的前 10 个 URL 和他们的出现次数,尽量利用 CPU 多核特性和内存资源。 * 根据[作业框架](https://github.com/pingcap/talent-plan/tree/master/tidb/mapreduce)完成作业,详细的作业要求、框架的使用方法和评分规则请看框架的 README 文件 ### Section 3 数据库基础知识 **学习资料:** * [《数据库系统概念》](https://book.douban.com/subject/1929984/)部分章节阅读和自学,或者 [CMU 15-445](https://15445.courses.cs.cmu.edu/fall2018/schedule.html) 对应部分内容 * 第 3 章:SQL * 第 11 章:索引与散列 * 第 12 章:查询处理 * 第 13 章:查询优化 * 第 14 章:事务 * 第 15 章:并发控制 * 第 18 章:并行数据库 * 第 19 章:分布式数据库 **课程作业:** * select t1.a, count(*), avg(t1.b) from t1 left outer join t2 on t1.a=t2.a group by t1.a,请给出所有可能的逻辑执行计划(画出 Plan 树),并分析 t1 的数据分布对各种逻辑执行计划执行性能的影响。画 Plan 树时可以利用 [Graphviz 作图](http://www.webgraphviz.com),例如对于 select * from t where a > 1,一个可能的执行计划可以如下图所示: ![Execution-example](../media/execution-example.jpg) ### Section 4 SQL 优化器和执行引擎基本原理 **学习资料:** * [CMU 15-721](https://15721.courses.cs.cmu.edu/spring2018/) 数据库课程,自学 + 在线视频教学 * Optimizer Implementation (Part I) * Optimizer Implementation (Part II) * Cost Models * Execution & Scheduling * Vectorized Execution (Part I) * Vectorized Execution (Part II) * Parallel Join Algorithms (Hashing) * Parallel Join Algorithms (Sorting) **课程作业:** * 用 Go 语言,实现一个 Join 算法,从两个 CSV 文件中读取数据,在一个或多个等值条件上进行连接,并对最终结果求和。请参考 [README](https://github.com/pingcap/talent-plan/tree/master/tidb/join) ,使用提供的框架完成作业,并跑通测试程序。提交的作业要求代码整洁规范,附有文档,并提供对程序的性能瓶颈分析及优化思路。 ### Section 5 阅读 TiDB 源码 **学习资料:** * [TiDB 源码阅读 24 章经](https://pingcap.com/blog-cn/#TiDB-%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB) **课程作业:** * 给 TiDB Repo 提 PR,例如修复 [for new contributors issues](https://github.com/pingcap/tidb/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+label%3A%22for+new+contributors%22+)。 ## 考核要点 完成各项作业,代码通过邮件提交到 ts-team@pingcap.com,要求使用 Golang 1.12,需要有代码、测试、注释、文档。 我们会根据以下规则进行评分,最终得到一个 0~100 分的分数 1. 代码可以跑过 PingCAP 提供的测试程序(一些题目有性能要求,希望在规定的时间内跑完)50% 2. 单元测试覆盖率 30% 3. [代码风格](https://github.com/pingcap/community/blob/master/CONTRIBUTING.md#code-style) 10% 4. 文档情况 10% ================================================ FILE: talent-plan-1.0/1.0-lp-tikv.md ================================================ # 路径 2:TiKV 方向 ## 课程目标 * 掌握 Rust 语言 * 掌握分布式一致性算法 Raft * 掌握分布式存储基本原理 ## 课程内容 ### Section 1 熟悉 Rust 语言基础知识 **学习资料:** * [Practical Networked Applications in Rust](https://github.com/pingcap/talent-plan/tree/master/courses/rust) * 阅读《[Rust 编程之道](https://book.douban.com/subject/30418895/)》或者《[深入浅出 Rust](https://book.douban.com/subject/30312231/)》或者 [Rust 官方教程](https://doc.rust-lang.org/book/) 三选一 **课程作业:** * 完成 [Practical Networked Applications in Rust](https://github.com/pingcap/talent-plan/tree/master/courses/rust) 中 Project 1、2(给该课程提出改进意见并帮助改进,根据意见及改进情况会有额外加分哦~) ### Section 2 熟悉 Rust 语言基础知识 **学习资料:** * [Practical Networked Applications in Rust](https://github.com/pingcap/talent-plan/tree/master/courses/rust) * 阅读《[Rust 编程之道](https://book.douban.com/subject/30418895/)》或者《[深入浅出 Rust](https://book.douban.com/subject/30312231/)》或者 [Rust 官方教程](https://doc.rust-lang.org/book/) 三选一 **课程作业:** * 完成 [Practical Networked Applications in Rust](https://github.com/pingcap/talent-plan/tree/master/courses/rust) 中 Project 3、4(给该课程提出改进意见并帮助改进,根据意见及改进情况会有额外加分哦~) ### Section 3 分布式存储基础知识 **学习资料:** * 学习 Raft Paper 和 [6.824 Lab 2: Raft](https://pdos.csail.mit.edu/6.824/labs/lab-raft.html) 线上课程 **课程作业:** * 使用 Rust 语言 完成 6.824 Lab 2 [raft 作业](https://github.com/pingcap/talent-plan/tree/master/dss) ### Section 4 分布式系统基础知识 **学习资料:** * 完成 [6.824 Lab 3: Fault-tolerant Key/Value Service](https://pdos.csail.mit.edu/6.824/labs/lab-kvraft.html) 线上课程 **课程作业:** * 使用 Rust 语言 完成 6.824 Lab 3 [kvraft 作业](https://github.com/pingcap/talent-plan/tree/master/dss) ### Section 5 阅读 TiKV 源码 **学习资料:** * [TiKV 源码解析](https://pingcap.com/blog-cn/#TiKV-%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90)(持续更新中) **课程作业:** * 给 TiKV Repo 提 PR,例如修复 [for new contributors issues](https://github.com/tikv/tikv/issues?q=is%3Aissue+is%3Aopen+label%3A%22D%3A+Easy%22+label%3A%22S%3A+HelpWanted%22)。 * 给 PD Repo 提 PR,例如修复 [for new contributors issues]()。 ## 考核方式 根据提交到程序是否能通过测试给出 Pass or Fail 1. 代码可以跑过 PingCAP 提供的测试程序 50% a. make check b. make test 2. 代码风格 30% 3. 文档情况 20% ================================================ FILE: talent-plan-1.0/README-CN.md ================================================ # Talent Plan Courses 1.0 Talent Plan 1.0 课程中共有 2 条学习路径供大家选择,分别是: * 面向分布式关系型数据库 SQL 层的 [TiDB 方向](1.0-lp-tidb.md) * 面向分布式 Key-value 数据库存储层的 [TiKV 方向](1.0-lp-tikv.md) 正在学习 Talent Plan 1.0 课程的小伙伴可通过上述链接查看相关路径的课程详情。 > ***特别提醒:*** > > Talent Plan 2.0 课程已正式上线,相比 1.0 版本,新增了用 Go 语言全新设计的分布式关系型数据库 TinySQL 课程和分布式 Key-value 数据库 TinyKV 课程,并结合大家的兴趣爱好和知识背景全新规划了 5 条推荐的学习路径,分别是: > > * 路径 1:[实现一个 Mini 版本的分布式关系型数据库](https://learn.pingcap.com/learner/talent-plan/implement-a-mini-distributed-relational-database) > * 路径 2:[实现一个 Mini 版本的分布式 Key-value 数据库](https://learn.pingcap.com/learner/talent-plan/implement-a-mini-distributed-key-value-database) > * 路径 3:[参与工业级开源分布式关系型数据库 TiDB 的开发实践](https://learn.pingcap.com/learner/talent-plan/become-a-tidb-contributor) > * 路径 4:[参与工业级开源分布式 Key-value 数据库 TiKV 的开发实践](https://learn.pingcap.com/learner/talent-plan/become-a-tikv-contributor) > * 路径 5:[Rust 编程原理与实践](>https://learn.pingcap.com/learner/talent-plan/rust-programming) > > 小伙伴们也可直接通过 [Talent Plan 官网](https://learn.pingcap.com/learner/talent-plan) 开始 Talent Plan 2.0 课程的学习。 ================================================ FILE: tidb/.gitignore ================================================ .idea/ ================================================ FILE: tidb/README.md ================================================ # Distributed Systems in Go * Week 1: [Merge Sort](./mergesort) * Week 2: [Map Reduce](./mapreduce) * Week 4: [Parallel Join](./join) ================================================ FILE: tidb/join/Makefile ================================================ .PHONY: all all: test bench test: go test bench: go test -bench Benchmark -run xx -count 5 -benchmem ================================================ FILE: tidb/join/README.md ================================================ ## Introduction This is the homework for PingCAP Talent Plan Online of week 4. This homework is a simplified version of [ACM SIGMOD Programming Contest 2018](http://sigmod18contest.db.in.tum.de/index.shtml). The task is to evaluate batches of join queries on a set of pre-defined relations. Each join query specifies two relations, multiple (equality) join predicates, and one (sum) aggregation. The challenge is to fully utilize the CPU and memory resources and execute the queries as fast as possible. NOTE: **go 1.12 is required** ## Details The simple interface `Join(f0, f1 string, offset0, offset1 []int) (sum uint64)` is defined in `join.go`. Our test harness will feed two relations and two columns' offsets array to the interface every time, and check the correctness of the output result. Explaination to the four input arguments and one output argument of the interface are list as follows: - **f0**: File name of the given relation0. - **f1**: File name of the given relation1. - **offset0**: Offsets of which columns the given relation0 should be joined. - **offset1**: Offsets of which columns the given relation1 should be joined. - **sum** (output argument): Sum of the relation0.col0 in the final join result. The (equality) join predicates are specified by the `offset0/1`. The form of the join predicates is like: ``` go relation0.cols[offset[0]] = relation1.cols[offset[0]] and relation0.cols[offset[1]] = relation1.cols[offset[1]]... ``` **Example**: `Join("/path/T0", "/path/T1", []int{0, 1}, []int{2, 3})` Translated to SQL: ``` sql SELECT SUM(T0.COL0) FROM T0, T1 ON T0.COL0=T1.COL2 AND T0.COL1=T1.COL3 ``` We provide a sample as `join_example.go: JoinExample` which performs a simple hash join algorithm. It uses the relation0 to build the hash table, and probe the hash table for every row in relation1. ## Requirements and rating principles - (30%) Pass all test cases. - (20%) Perform better than `join_example.go:JoinExample`. - (35%) Have a document to describe your idea and record the process of performance optimization with `pprof`. - (15%) Keep a good code style. Note: 1. For your check sums, you do not have to worry about numeric overflows as long as you are using 64 bit unsigned integers. 2. More large datasets are provided [here](https://drive.google.com/drive/u/1/folders/10-iJNGKmKXgMmvBYnKt88RTwC0iA1XM-), you can use them to help profile your program. 3. We'll use the `BenchmarkJoin` and `BenchmarkJoinExample` which can be found in `benchmark_test.go` to evaluate your program. Test data will **NOT** be outside of what we've provided. ## How to use 1. Please implement your own `Join` in join.go to accomplish this task. 2. We provide CSV versions (.tbl files) of three relations in directory `t`. You can load them into a DBMS to test your program. 1. **r0.tbl**: 2 columns * 10,000 records 2. **r1.tbl**: 4 columns * 5,000 records 3. **r2.tbl**: 4 columns * 500 records 3. There is already a built-in unit test `JoinTest` defined in `join_test.go`. You can write your own unit tests, but please make sure `JoinTest` can be passed before. 4. Use `make test` to run all the unit tests. 5. Use `make bench` to run all the benchmarks. ================================================ FILE: tidb/join/benchmark_test.go ================================================ package main import "testing" func BenchmarkJoin(b *testing.B) { for i := 0; i < b.N; i++ { Join("./t/r0.tbl", "./t/r2.tbl", []int{0}, []int{1}) } } func BenchmarkJoinExample(b *testing.B) { for i := 0; i < b.N; i++ { JoinExample("./t/r0.tbl", "./t/r2.tbl", []int{0}, []int{1}) } } ================================================ FILE: tidb/join/go.mod ================================================ module join go 1.12 require ( github.com/pingcap/check v0.0.0-20171206051426-1c287c953996 github.com/pingcap/tidb v2.1.7+incompatible ) ================================================ FILE: tidb/join/go.sum ================================================ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/apache/thrift v0.0.0-20161221203622-b2a4d4ae21c7/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/beorn7/perks v0.0.0-20160229213445-3ac7bf7a47d1/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/blacktear23/go-proxyprotocol v0.0.0-20180807104634-af7a81e8dd0d/go.mod h1:VKt7CNAQxpFpSDz3sXyj9hY/GbVsQCr0sB3w59nE7lU= github.com/cockroachdb/cmux v0.0.0-20170110192607-30d10be49292/go.mod h1:qRiX68mZX1lGBkTWyp3CLcenw9I94W2dLeRvMzcn9N4= github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.2.18+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180202092358-40e2722dffea/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cznic/mathutil v0.0.0-20160613104831-78ad7f262603/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= github.com/cznic/sortutil v0.0.0-20150617083342-4c7342852e65/go.mod h1:q2w6Bg5jeox1B+QkJ6Wp/+Vn0G/bo3f1uY7Fn3vivIQ= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/etcd-io/gofail v0.0.0-20180808172546-51ce9a71510a/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-sql-driver/mysql v0.0.0-20170715192408-3955978caca4/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20181024230925-c65c006176ff/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20161217183710-316fb6d3f031/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/gorilla/context v0.0.0-20160226214623-1ea25387ff6f/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v0.0.0-20170228224354-599cba5e7b61/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20171020063731-82921fcf811d/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v0.0.0-20160910222444-6b7015e65d36/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.4.1/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/montanaflynn/stats v0.0.0-20151014174947-eeaced052adb/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/ngaut/pools v0.0.0-20180318154953-b7bc8c42aac7/go.mod h1:iWMfgwqYW+e8n5lC/jjNEhwcjbRDpl5NT7n2h+4UNcI= github.com/ngaut/sync2 v0.0.0-20141008032647-7a24ed77b2ef/go.mod h1:7WjlapSfwQyo6LNmIvEWzsW1hbBQfpUO4JWnuQRmva8= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pingcap/check v0.0.0-20171206051426-1c287c953996 h1:ZBdiJCMan6GSo/aPAM7gywcUKa0z58gczVrnG6TQnAQ= github.com/pingcap/check v0.0.0-20171206051426-1c287c953996/go.mod h1:B1+S9LNcuMyLH/4HMTViQOJevkGiik3wW2AN9zb2fNQ= github.com/pingcap/errors v0.11.1/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pingcap/gofail v0.0.0-20181217135706-6a951c1e42c3/go.mod h1:DazNTg0PTldtpsQiT9I5tVJwV1onHMKBBgXzmJUlMns= github.com/pingcap/goleveldb v0.0.0-20171020084629-8d44bfdf1030/go.mod h1:O17XtbryoCJhkKGbT62+L2OlrniwqiGLSqrmdHCMzZw= github.com/pingcap/kvproto v0.0.0-20190226063853-f6c0b7ffff11/go.mod h1:0gwbe1F2iBIjuQ9AH0DbQhL+Dpr5GofU8fgYyXk+ykk= github.com/pingcap/parser v0.0.0-20190328044348-9945885931bb/go.mod h1:1FNvfp9+J0wvc4kl8eGNh7Rqrxveg15jJoWo/a0uHwA= github.com/pingcap/pd v2.1.0-rc.4+incompatible/go.mod h1:nD3+EoYes4+aNNODO99ES59V83MZSI+dFbhyr667a0E= github.com/pingcap/tidb v2.1.7+incompatible h1:ZkaxiVAKb6dqAZdA3CkzmYPBEugQ0e/w7hXEhYiwEfE= github.com/pingcap/tidb v2.1.7+incompatible/go.mod h1:gTnPm64oI1Z1y/LEB3NUcxEgFy8NRswlmgTRiBCrijw= github.com/pingcap/tidb-tools v2.1.3-0.20190116051332-34c808eef588+incompatible/go.mod h1:XGdcy9+yqlDSEMTpOXnwf3hiTeqrV6MN/u1se9N8yIM= github.com/pingcap/tipb v0.0.0-20180910045846-371b48b15d93/go.mod h1:RtkHW8WbcNxj8lsbzjaILci01CtYnYbIkQhjyZWrWVI= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/common v0.0.0-20180426121432-d811d2e9bf89/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/procfs v0.0.0-20180408092902-8b1c2da0d56d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/sirupsen/logrus v0.0.0-20170323161349-3bcb09397d6d/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/spaolacci/murmur3 v0.0.0-20150829172844-0d12bf811670/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/twinj/uuid v0.0.0-20150629100731-70cac2bcd273/go.mod h1:mMgcE1RHFUFqe5AfiwlINXisXfDGro23fWdPUfOMjRY= github.com/uber/jaeger-client-go v2.8.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v1.1.0/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/ugorji/go v1.1.1/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= github.com/unrolled/render v0.0.0-20171102162132-65450fb6b2d3/go.mod h1:tu82oB5W2ykJRVioYsB+IQKcft7ryBr7w12qMBUPyXg= github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= golang.org/x/crypto v0.0.0-20180503215945-1f94bef427e3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20181105230042-78dc5bac0cac/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= google.golang.org/genproto v0.0.0-20180427144745-86e600f69ee4/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/natefinch/lumberjack.v2 v2.0.0-20161104145732-dd45e6a67c53/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= ================================================ FILE: tidb/join/join.go ================================================ package main // Join accepts a join query of two relations, and returns the sum of // relation0.col0 in the final result. // Input arguments: // f0: file name of the given relation0 // f1: file name of the given relation1 // offset0: offsets of which columns the given relation0 should be joined // offset1: offsets of which columns the given relation1 should be joined // Output arguments: // sum: sum of relation0.col0 in the final result func Join(f0, f1 string, offset0, offset1 []int) (sum uint64) { return sum } ================================================ FILE: tidb/join/join_example.go ================================================ package main import ( "encoding/csv" "io" "os" "strconv" "unsafe" "github.com/pingcap/tidb/util/mvmap" ) // JoinExample performs a simple hash join algorithm. func JoinExample(f0, f1 string, offset0, offset1 []int) (sum uint64) { tbl0, tbl1 := readCSVFileIntoTbl(f0), readCSVFileIntoTbl(f1) hashtable := buildHashTable(tbl0, offset0) for _, row := range tbl1 { rowIDs := probe(hashtable, row, offset1) for _, id := range rowIDs { v, err := strconv.ParseUint(tbl0[id][0], 10, 64) if err != nil { panic("JoinExample panic\n" + err.Error()) } sum += v } } return sum } func readCSVFileIntoTbl(f string) (tbl [][]string) { csvFile, err := os.Open(f) if err != nil { panic("ReadFileIntoTbl " + f + " fail\n" + err.Error()) } defer csvFile.Close() csvReader := csv.NewReader(csvFile) for { row, err := csvReader.Read() if err == io.EOF { break } else if err != nil { panic("ReadFileIntoTbl " + f + " fail\n" + err.Error()) } tbl = append(tbl, row) } return tbl } func buildHashTable(data [][]string, offset []int) (hashtable *mvmap.MVMap) { var keyBuffer []byte valBuffer := make([]byte, 8) hashtable = mvmap.NewMVMap() for i, row := range data { for j, off := range offset { if j > 0 { keyBuffer = append(keyBuffer, '_') } keyBuffer = append(keyBuffer, []byte(row[off])...) } *(*int64)(unsafe.Pointer(&valBuffer[0])) = int64(i) hashtable.Put(keyBuffer, valBuffer) keyBuffer = keyBuffer[:0] } return } func probe(hashtable *mvmap.MVMap, row []string, offset []int) (rowIDs []int64) { var keyHash []byte var vals [][]byte for i, off := range offset { if i > 0 { keyHash = append(keyHash, '_') } keyHash = append(keyHash, []byte(row[off])...) } vals = hashtable.Get(keyHash, vals) for _, val := range vals { rowIDs = append(rowIDs, *(*int64)(unsafe.Pointer(&val[0]))) } return rowIDs } ================================================ FILE: tidb/join/join_test.go ================================================ package main import ( "testing" "github.com/pingcap/check" ) type joinTestSuite struct{} func TestT(t *testing.T) { check.TestingT(t) } var _ = check.Suite(&joinTestSuite{}) func (s *joinTestSuite) TestJoin(c *check.C) { for _, t := range []struct { f0 string f1 string offsets0 []int offsets1 []int sum uint64 }{ // r0 join r0 on r0.col0 = r0.col1 {"./t/r0.tbl", "./t/r0.tbl", []int{0}, []int{1}, 0x16CBF2D}, // r0 join r1 on r0.col0 = r1.col0 {"./t/r0.tbl", "./t/r1.tbl", []int{0}, []int{0}, 0xC1D73B}, // r0 join r1 on r0.col1 = r1.col1 {"./t/r0.tbl", "./t/r1.tbl", []int{1}, []int{1}, 0x33010}, // r0 join r2 on r0.col0 = r2.col0 {"./t/r0.tbl", "./t/r2.tbl", []int{0}, []int{0}, 0x1F235}, // r0 join r1 on r0.col0 = r1.col0 and r0.col1 = r1.col1 {"./t/r0.tbl", "./t/r1.tbl", []int{0, 1}, []int{0, 1}, 0}, // r1 join r2 on r1.col0 = r2.col0 {"./t/r1.tbl", "./t/r2.tbl", []int{0}, []int{0}, 0x18CDA}, // r2 join r2 on r2.col0 = r2.col0 and r2.col1 = r2.col1 {"./t/r2.tbl", "./t/r2.tbl", []int{0, 1}, []int{0, 1}, 0x5B385}, } { c.Assert(Join(t.f0, t.f1, t.offsets0, t.offsets1), check.Equals, t.sum) //c.Assert(JoinExample(t.f0, t.f1, t.offsets0, t.offsets1), check.Equals, t.sum) } } ================================================ FILE: tidb/join/t/r0.tbl ================================================ 1,7277 3,7506 7,10488 11,4923 15,7803 19,9251 23,9239 28,9961 31,8944 33,5726 38,4517 39,10350 41,9926 42,9587 45,8220 48,10129 53,8545 57,8798 61,9511 65,6292 70,8270 74,5872 76,10476 80,5238 84,4526 88,10457 90,4690 92,8501 93,6074 95,4963 99,4912 103,7256 105,8893 110,5515 112,7236 115,4410 116,5315 118,9120 120,5690 122,5233 124,8281 129,7944 133,5938 136,7374 141,6798 143,10119 148,8310 152,8499 153,9619 155,5308 158,5652 161,4710 165,9509 166,9760 167,6465 170,7678 173,6813 175,6440 176,8871 180,4844 184,9571 186,10474 190,4853 193,5550 196,8969 201,9483 205,7933 206,7523 208,5712 210,6323 214,7833 215,6972 218,8080 219,7886 221,7354 223,5753 228,8325 229,5311 231,6620 233,4740 236,5223 241,8910 244,6436 249,10466 253,6984 256,4538 259,4826 263,10068 266,5143 267,7806 272,5397 274,4753 277,7158 282,7853 285,9511 288,5627 290,8405 293,7451 296,7757 297,9185 301,6271 303,10280 306,8365 310,5060 312,4963 313,7233 315,6833 318,9620 323,5943 326,10264 328,7806 333,8872 336,7349 338,5164 340,5683 343,9871 348,8282 353,10359 356,5812 361,10326 364,9617 365,9742 367,7932 368,8939 370,9908 374,5557 378,9549 380,4901 383,10448 386,6573 389,6316 394,5673 395,6375 399,10418 404,5357 409,4768 412,6016 416,7066 420,8490 424,6898 425,7918 428,8476 430,7351 431,10057 436,8888 438,6230 439,4694 444,6040 448,5281 451,5417 454,10234 455,9680 459,9131 461,9765 464,6222 468,5758 469,4598 470,8842 472,8646 477,6319 479,4484 482,9191 487,9568 492,5001 493,10163 495,9019 497,7644 498,9985 499,7325 502,8265 507,9745 512,7781 513,7515 514,8298 517,8594 521,8455 522,7597 526,4816 529,9929 532,7925 536,6556 540,9694 542,6231 544,5519 548,8895 551,10203 552,10381 554,8292 558,10222 563,7926 567,4950 571,9908 573,4467 578,9728 583,4653 587,7474 591,7705 595,10210 598,7467 603,6825 605,6859 607,9596 612,10260 615,5839 618,7957 619,8949 621,7603 622,5941 624,7996 629,10282 631,9241 632,5027 635,7014 639,4503 642,10056 647,5240 648,5224 649,9975 651,9652 652,9717 657,9212 662,4839 666,9756 669,7389 673,4787 678,10024 682,7094 684,6293 685,7735 689,9923 692,6520 693,8221 694,9630 698,8973 702,9258 706,5488 711,10029 713,7911 717,8989 722,9743 723,9530 725,6079 730,7916 731,8770 733,9031 734,6312 736,9181 740,5953 744,4805 749,6207 754,5192 755,6609 756,5856 757,8472 758,7030 762,10444 766,10191 769,5257 770,4973 775,7927 778,4393 780,6397 783,9088 787,6836 789,9095 794,9427 799,6934 802,8264 803,9396 805,8423 809,4725 810,7180 813,8586 814,8526 818,4720 823,8517 825,6612 828,6567 833,7116 838,5350 843,4713 848,6627 852,7244 857,9775 861,7846 864,9033 867,10258 872,5618 875,5941 878,6907 880,10349 884,8569 886,5592 890,7291 891,7573 893,9637 898,6788 901,5582 902,4609 906,5535 908,4986 910,7361 913,7996 917,5364 921,10314 923,7891 927,5000 928,6069 933,7643 937,10187 942,9896 944,6979 946,9095 948,4756 951,8020 955,7881 956,8376 960,6799 963,10091 966,6513 967,7693 970,7224 972,9087 975,4989 976,8167 979,8595 983,7167 985,9632 989,7301 994,5828 995,8775 997,7664 1000,10380 1005,9992 1006,5734 1009,6388 1011,7844 1012,9894 1014,6070 1017,7131 1022,7940 1024,9600 1029,9654 1032,8685 1035,9966 1039,5315 1042,7555 1043,8965 1046,4984 1051,7888 1053,7528 1056,6184 1061,7043 1065,8633 1067,5221 1071,4758 1076,7848 1079,4531 1081,7294 1083,7791 1084,7447 1088,10226 1090,9111 1091,10254 1095,8064 1098,7454 1099,7731 1103,10136 1107,5929 1108,9066 1113,7688 1118,7072 1120,10095 1123,7521 1126,9518 1131,6713 1133,9033 1137,5858 1139,5210 1142,6673 1147,8269 1149,6816 1151,4594 1155,6072 1159,7276 1163,9836 1166,6083 1167,6102 1169,5179 1174,4912 1177,7237 1182,5796 1183,9549 1186,9077 1189,10189 1190,10090 1194,7008 1199,10285 1201,8315 1206,5772 1211,5299 1216,5593 1217,4549 1221,9490 1225,9836 1227,8259 1228,5508 1233,8065 1237,5976 1238,6911 1239,9369 1242,9546 1243,6502 1248,5414 1253,5052 1254,4925 1255,9901 1259,5967 1260,7665 1261,9451 1262,5869 1264,9502 1269,6775 1273,9415 1276,5202 1277,8525 1282,8991 1287,9049 1290,8737 1294,8589 1296,8776 1300,7637 1302,7917 1304,5595 1305,9026 1307,6624 1310,7162 1315,7082 1320,6476 1324,5320 1325,10396 1326,8920 1331,8421 1334,9876 1337,4671 1341,9491 1342,5430 1346,5273 1350,5969 1354,10123 1358,5315 1359,9410 1363,9007 1368,8232 1373,6748 1375,6131 1379,8366 1381,7979 1384,7914 1389,8519 1391,8386 1395,5328 1400,4808 1405,5811 1407,4769 1408,5117 1411,5924 1415,8696 1420,9794 1422,4390 1423,8938 1428,9372 1431,5987 1435,6058 1436,7005 1441,9688 1445,5342 1448,7999 1452,7803 1455,5204 1459,6974 1462,7756 1463,5756 1464,9201 1466,6582 1471,6088 1476,9061 1477,8382 1479,8464 1482,9401 1483,4734 1487,8199 1489,5777 1491,7771 1494,7987 1497,7878 1499,7558 1501,7273 1503,5268 1505,8377 1506,7176 1507,7244 1508,8975 1510,7066 1511,4814 1514,5137 1516,9023 1520,8105 1522,10168 1526,6293 1531,8826 1533,7160 1538,10210 1539,4838 1541,8211 1544,6956 1548,8600 1551,4985 1553,5370 1555,7960 1558,7357 1560,6390 1561,5608 1565,7990 1566,7088 1567,5818 1568,6763 1571,9086 1575,6478 1577,10396 1578,4559 1579,10427 1581,7208 1584,4420 1585,7553 1588,5568 1589,5176 1590,9892 1592,6517 1593,6323 1597,10412 1600,5759 1602,7607 1605,8697 1610,9190 1615,8451 1617,6745 1620,5400 1622,10354 1623,9562 1625,7909 1629,9818 1632,8847 1635,6554 1640,9111 1642,10036 1646,4644 1647,7199 1650,8663 1653,5812 1655,9240 1660,5563 1664,5509 1667,8453 1669,8779 1673,7276 1677,9604 1678,8885 1680,8977 1684,4773 1688,9261 1691,5918 1694,7061 1695,10201 1696,9475 1700,7620 1703,5220 1708,9415 1710,6116 1712,9805 1716,5090 1720,6335 1722,4672 1725,9134 1729,9299 1730,8985 1733,10309 1736,6914 1737,7457 1742,10142 1745,7070 1748,7798 1750,7171 1751,4958 1752,6464 1756,8564 1761,7361 1765,8864 1766,9040 1768,6444 1773,6184 1776,7370 1780,4644 1784,4558 1789,8466 1793,5947 1794,5223 1795,8223 1799,9621 1802,9829 1804,4436 1809,5881 1814,8039 1817,5470 1818,8455 1821,9113 1826,4844 1827,7084 1831,10439 1835,4917 1838,5530 1843,5887 1844,4882 1847,9021 1851,9495 1854,8497 1859,8219 1863,6205 1865,6381 1866,9639 1871,10148 1875,8104 1877,5031 1879,8634 1882,5753 1884,6757 1889,9628 1891,8705 1893,9107 1898,8055 1901,5012 1906,6555 1909,4547 1912,10433 1915,6114 1917,9116 1922,6679 1926,9272 1931,5574 1933,6436 1935,10086 1939,4512 1940,10174 1941,10011 1943,9015 1945,4522 1948,4808 1953,4857 1954,6494 1957,6542 1960,6260 1964,9410 1965,9809 1968,9731 1971,5295 1974,7021 1977,8020 1981,5342 1982,9142 1983,7845 1985,5820 1988,10226 1992,10235 1995,8650 1998,4932 2000,6921 2003,9981 2005,6204 2006,6566 2010,4599 2011,6101 2012,4778 2017,10347 2018,8974 2019,6006 2023,6796 2027,4564 2029,9375 2032,8903 2037,9163 2042,8090 2047,9057 2052,5187 2057,6460 2061,9057 2064,9834 2065,7239 2068,9650 2072,4530 2076,9893 2077,7923 2079,10169 2080,8047 2083,5550 2088,6482 2093,10036 2096,6729 2098,9983 2100,4414 2101,8383 2106,7421 2108,4510 2110,9079 2113,6462 2116,8269 2120,6462 2121,9043 2123,5382 2128,8659 2133,5105 2134,5342 2139,7658 2144,5907 2145,6401 2149,8059 2154,5382 2156,8232 2160,10446 2165,9031 2167,9803 2168,5073 2172,5585 2177,7539 2180,4467 2185,9914 2188,8545 2192,9416 2193,10095 2198,10211 2199,8149 2203,9106 2204,4713 2206,5857 2208,9447 2213,10467 2218,6396 2221,6879 2226,7401 2230,6352 2231,4986 2234,6779 2237,8781 2241,7901 2244,6120 2245,9275 2247,4883 2250,7709 2252,5097 2255,4660 2259,8412 2263,7740 2265,9544 2270,4955 2273,6706 2274,6272 2279,5204 2280,7956 2284,9563 2287,10455 2291,4530 2293,9210 2298,5001 2303,5843 2307,9610 2310,10259 2311,7089 2312,7902 2317,8559 2321,8753 2324,6153 2326,4514 2331,6268 2335,9864 2340,7287 2345,5284 2346,8311 2348,5106 2352,5127 2356,5968 2357,6363 2361,7403 2364,7130 2368,4532 2373,6100 2378,6864 2382,10444 2384,5849 2389,8715 2392,5112 2393,6702 2397,5454 2400,6313 2402,10295 2406,6193 2407,8075 2410,7538 2413,10130 2416,9100 2417,8540 2420,6668 2422,6591 2426,5845 2428,5957 2429,9710 2434,5453 2435,7809 2436,9462 2441,7342 2443,9313 2445,8232 2450,4547 2454,5483 2458,9827 2459,10197 2462,4698 2465,8934 2469,7188 2471,9834 2476,7526 2481,7392 2485,5909 2488,9193 2491,9461 2495,7131 2497,5213 2499,6575 2501,5725 2503,8467 2505,5221 2508,4508 2510,10249 2513,7479 2516,6682 2519,8839 2522,4799 2525,8286 2530,5883 2535,7215 2537,10340 2540,4924 2541,5165 2546,5130 2549,8784 2552,9545 2556,9992 2558,9046 2559,7940 2560,9044 2563,9801 2567,9619 2570,4424 2571,7939 2576,6912 2580,9732 2581,10079 2583,8216 2587,4792 2590,10129 2594,9226 2599,4427 2601,6992 2603,5306 2606,10217 2610,9030 2615,7862 2617,6077 2620,8987 2625,9781 2627,7660 2629,8774 2634,9694 2636,8908 2638,10383 2642,5059 2646,9004 2649,5388 2652,10096 2655,6749 2660,7571 2665,7416 2669,9936 2674,9237 2675,8034 2677,5532 2682,5803 2685,10452 2687,9557 2691,4983 2696,7414 2701,6115 2706,4671 2710,5068 2714,7702 2718,9038 2720,4817 2722,8288 2726,8500 2730,7702 2731,5803 2733,9409 2734,4919 2738,8358 2739,10077 2740,8103 2743,8498 2746,8032 2750,7522 2753,7906 2758,6960 2762,5539 2763,9530 2764,6699 2769,8397 2774,5800 2779,4624 2782,4766 2784,8879 2788,7059 2791,5954 2794,6695 2799,4867 2803,7361 2806,5629 2810,5402 2814,9216 2816,8961 2820,5186 2822,8021 2826,9683 2829,4792 2833,4745 2836,7146 2837,10417 2840,6180 2841,7271 2844,10010 2846,6680 2849,4690 2851,8377 2856,9952 2859,7719 2860,10121 2863,5122 2864,6847 2866,8018 2871,8918 2873,7493 2876,7881 2879,5481 2880,6031 2882,10068 2886,6465 2888,5005 2892,7221 2896,5411 2900,7533 2902,10110 2903,7937 2908,5956 2913,6221 2915,6903 2917,5675 2921,9144 2924,7329 2925,10184 2929,8083 2930,6669 2931,5730 2932,7211 2936,5458 2941,10291 2945,4778 2948,6924 2952,6030 2957,9828 2958,9195 2961,4785 2965,7455 2970,8559 2971,9041 2976,4797 2981,9065 2986,8056 2989,10091 2994,8614 2995,7790 2999,8030 3003,8901 3007,5952 3009,8640 3012,5392 3017,5399 3021,9609 3026,5241 3030,10067 3031,8665 3032,8287 3034,5673 3035,7409 3036,5068 3041,9234 3042,8345 3047,4920 3050,5850 3051,4691 3054,9898 3057,8258 3061,7001 3063,6133 3068,4439 3073,6056 3078,6340 3079,9473 3083,10204 3084,5438 3086,8317 3091,4513 3093,4763 3095,10358 3098,6572 3100,10046 3102,4511 3106,10063 3111,10234 3112,10011 3115,4392 3119,4868 3120,9725 3122,7551 3126,4668 3129,9770 3132,9515 3133,7039 3135,6500 3136,5671 3141,9921 3142,9516 3146,9298 3147,10342 3150,5173 3152,5051 3155,8336 3159,5415 3160,6109 3163,5676 3166,8538 3168,10034 3170,10375 3174,4622 3176,9722 3177,5716 3181,9629 3185,6084 3190,10253 3194,8353 3198,6661 3201,10342 3205,4749 3207,5639 3210,4556 3211,4770 3212,5325 3216,5714 3217,4729 3218,5580 3222,7466 3223,8039 3227,5714 3230,8602 3233,4707 3237,7296 3242,6617 3245,10484 3246,5881 3249,7177 3251,7406 3252,9961 3254,9412 3257,5657 3259,7335 3260,6463 3264,5416 3267,7259 3270,8013 3271,7684 3272,5841 3275,7166 3277,9358 3278,8866 3282,4493 3283,5991 3288,5280 3290,9554 3294,9124 3298,9527 3300,9704 3301,6313 3304,7409 3307,9940 3311,6340 3316,10291 3318,7988 3320,9500 3324,9422 3329,6491 3330,5776 3332,8306 3337,9692 3340,10157 3344,5494 3345,7411 3348,7615 3349,8896 3351,6396 3355,4548 3359,5783 3360,4745 3363,5372 3367,5413 3370,10065 3373,9296 3374,6279 3375,8654 3379,9475 3384,9273 3386,5021 3389,7136 3390,7721 3391,7830 3393,8621 3394,8544 3398,8513 3399,7072 3400,10388 3403,8517 3406,5448 3411,6538 3413,8234 3417,6230 3420,9564 3422,4515 3423,7765 3427,8116 3431,7524 3433,6682 3438,8073 3442,10298 3446,4830 3447,9319 3452,9176 3457,5310 3461,6927 3462,4541 3463,9205 3466,7980 3471,5621 3472,7001 3474,5526 3479,6732 3483,8555 3486,9932 3490,8402 3491,8188 3493,6333 3494,8194 3496,10013 3501,9414 3503,9526 3508,5698 3510,7190 3513,5413 3518,4794 3520,9949 3523,6862 3528,4562 3533,8460 3537,4782 3540,5437 3545,8348 3550,9595 3552,7318 3553,4944 3554,5472 3556,6471 3560,8116 3564,10266 3567,6965 3572,5637 3574,8511 3579,7285 3583,10400 3584,7300 3586,9395 3591,10136 3592,9740 3593,4667 3596,7070 3601,7967 3606,7356 3607,8882 3608,10464 3612,6870 3615,6067 3618,8245 3621,7987 3626,7584 3629,8432 3631,7717 3633,8536 3636,7634 3637,6619 3638,10003 3641,7131 3642,9322 3645,10369 3646,9338 3647,6315 3652,7162 3653,7405 3654,7716 3657,6680 3659,7226 3664,6949 3665,5574 3667,10272 3669,7743 3673,8770 3677,5176 3682,4547 3685,6187 3689,10099 3693,10431 3698,10313 3702,10069 3704,9976 3706,10388 3711,6829 3714,6649 3715,7500 3717,6708 3722,8405 3725,9477 3729,8372 3733,8974 3738,9863 3742,10162 3747,8353 3750,5939 3752,8982 3756,5094 3761,9144 3765,7913 3770,5542 3771,9141 3776,9981 3781,6550 3784,8652 3786,8227 3791,8227 3796,10176 3798,6911 3801,10237 3806,7023 3811,9056 3816,9672 3817,5388 3820,7040 3825,8320 3827,9950 3829,7928 3830,6810 3834,6060 3837,8313 3840,10278 3845,9908 3846,4481 3848,6300 3851,10201 3855,5480 3858,6607 3862,6899 3863,6470 3867,9740 3871,8913 3874,5703 3875,8385 3880,5470 3883,9191 3888,4765 3893,8901 3896,9973 3901,5751 3905,5035 3910,7016 3912,5108 3915,9541 3917,5508 3922,9774 3925,4935 3926,9395 3929,5975 3933,9229 3937,6603 3941,7007 3946,4440 3951,8097 3954,7172 3958,5265 3963,8382 3965,8033 3967,10408 3969,7052 3973,5249 3976,5674 3981,6382 3982,8399 3986,7585 3991,6840 3994,8602 3995,8039 3996,6479 3997,6103 4001,7826 4004,6720 4008,8368 4011,9538 4016,5486 4018,5219 4022,6752 4027,6969 4030,8878 4033,7432 4038,6096 4042,5779 4044,5599 4049,7531 4053,5176 4055,7267 4056,9134 4058,8536 4061,4833 4063,4502 4064,7291 4067,9075 4068,8811 4072,4599 4075,10035 4080,8219 4083,5793 4085,6406 4086,10196 4088,5364 4089,10268 4092,4972 4097,7993 4100,5814 4101,8802 4106,6264 4110,6327 4111,6857 4114,8453 4119,7651 4122,9340 4125,5367 4130,5543 4134,5449 4136,8098 4138,8736 4141,8283 4143,8411 4148,8118 4150,8632 4153,8369 4156,5994 4161,5536 4163,8976 4168,5019 4169,4600 4173,4578 4178,9815 4182,9663 4183,5883 4184,6289 4187,8743 4190,4429 4192,7557 4195,8279 4196,9677 4199,9888 4202,6771 4207,5650 4212,6101 4213,9799 4217,5229 4220,7845 4221,9081 4224,4512 4229,9824 4230,9069 4233,9009 4234,6706 4239,5374 4244,4420 4245,9306 4249,8406 4253,10199 4256,4666 4260,8701 4262,7683 4266,7241 4269,7593 4271,9008 4276,9319 4278,6184 4280,5147 4283,8593 4285,10078 4290,8967 4291,5576 4293,8485 4294,6157 4297,6176 4300,10443 4304,7688 4306,8932 4308,6195 4310,5073 4313,8876 4315,10432 4318,10440 4322,8610 4327,9371 4329,6866 4331,9791 4333,8134 4335,6792 4338,5740 4343,6553 4345,4974 4349,9806 4354,7950 4355,10141 4356,10371 4360,6072 4362,9340 4366,4482 4368,7376 4370,7514 4371,7644 4376,4880 4379,10174 4383,10436 4387,5168 4392,10213 4396,8283 4398,7985 4403,10232 4405,5559 4409,6585 4413,7492 4417,9145 4421,10121 4423,9853 4425,4910 4429,9572 4431,8821 4435,7198 4437,7813 4440,6955 4441,7539 4443,6109 4448,9351 4453,9672 4456,7426 4459,8259 4463,9168 4465,8045 4470,10436 4475,5430 4477,4483 4479,4578 4484,4377 4488,7880 4493,8014 4498,8151 4501,8959 4506,5207 4508,8626 4512,6509 4513,4511 4517,10243 4521,4567 4524,9734 4527,5945 4531,7910 4532,9988 4537,8880 4542,6279 4546,7045 4548,7779 4550,4545 4551,5631 4552,8550 4553,4695 4555,6755 4557,7197 4561,8712 4564,6411 4565,5211 4570,5200 4571,10387 4572,8718 4577,6220 4581,4966 4583,8214 4588,5981 4590,7991 4594,7312 4597,5954 4600,5765 4602,9739 4605,5004 4609,5314 4610,4462 4611,9379 4614,6144 4616,10342 4620,8107 4624,7573 4626,6883 4630,6063 4632,8885 4634,5967 4635,8173 4639,6290 4640,6126 4644,5678 4647,5835 4652,9694 4654,7747 4655,7035 4658,6841 4663,9602 4667,6097 4670,9762 4674,4973 4678,6296 4679,4603 4683,10165 4686,10346 4690,9068 4693,10279 4694,7804 4699,5539 4701,6923 4702,8195 4705,9483 4708,7264 4711,8051 4714,5341 4717,5958 4721,7315 4725,9808 4727,5299 4730,8971 4731,6578 4736,6966 4741,5012 4742,6199 4747,5795 4752,5686 4753,10249 4755,7305 4759,5960 4762,8946 4767,5931 4771,9875 4772,5836 4777,9676 4779,10358 4780,8394 4785,9982 4790,7114 4791,6042 4792,5384 4793,9319 4795,8558 4800,6448 4803,4668 4806,8136 4808,5293 4810,10165 4815,6485 4817,7408 4822,8051 4825,8808 4828,6492 4830,7719 4835,8768 4839,6418 4843,8329 4844,8733 4845,7572 4850,6838 4855,7167 4857,9032 4861,10060 4865,7233 4866,5217 4871,4862 4875,4497 4879,7356 4882,4460 4884,6376 4886,4721 4890,10023 4893,4855 4895,7531 4899,9728 4903,7856 4907,9747 4910,9872 4915,9208 4919,7098 4923,5025 4924,5503 4929,4746 4930,4644 4935,6186 4937,5615 4940,5374 4942,7597 4943,10396 4948,10259 4953,9604 4955,6764 4959,4578 4962,10253 4964,7668 4966,7296 4971,8210 4976,9428 4980,6660 4984,7192 4988,7559 4989,8517 4991,5843 4993,5055 4995,4549 4998,4450 4999,5720 5000,6818 5002,7309 5003,10438 5006,5578 5011,4967 5013,7162 5016,8054 5021,10094 5022,7697 5027,7267 5029,9730 5031,7968 5032,6754 5033,7509 5036,7270 5037,7647 5040,9526 5043,8181 5044,9632 5048,7554 5050,4388 5055,5774 5057,6842 5061,5027 5062,8573 5064,4886 5066,4815 5071,4558 5073,6908 5076,6491 5079,6056 5081,8834 5086,5978 5088,5790 5092,9496 5095,5355 5097,5507 5099,10068 5103,9715 5106,10243 5110,9759 5111,5536 5116,9668 5120,10148 5124,4684 5127,7854 5129,6078 5131,10285 5132,5382 5133,6976 5136,6396 5140,9099 5143,9516 5144,5471 5146,7748 5148,7972 5151,8070 5156,8299 5161,7077 5162,9951 5166,4906 5171,10436 5172,4527 5173,6429 5178,6014 5183,7412 5184,8636 5189,8206 5190,8763 5195,7999 5199,6854 5203,6452 5206,9343 5210,4594 5212,6942 5217,9856 5221,9710 5222,5498 5224,8685 5228,9817 5229,10230 5231,8684 5236,7156 5240,9063 5242,7321 5243,5336 5248,7001 5250,10274 5253,8697 5256,10047 5258,4887 5261,9349 5266,6681 5268,8639 5270,10478 5272,9747 5276,8517 5279,6091 5280,5098 5285,8228 5290,10459 5295,9313 5300,10077 5301,6018 5303,8701 5305,7662 5306,6628 5310,7058 5314,9086 5319,4577 5320,5542 5324,5982 5329,9801 5330,10455 5332,5318 5336,9607 5340,8538 5341,6483 5343,6861 5348,4861 5351,5187 5355,8613 5356,8200 5360,7325 5363,9470 5364,8941 5365,4594 5370,7583 5375,6500 5377,10346 5380,6586 5383,5088 5384,5678 5386,4809 5391,7903 5395,6586 5396,7090 5397,4516 5399,9287 5402,7100 5404,9326 5409,8988 5413,5201 5418,7361 5423,9732 5426,8470 5431,10242 5433,6718 5435,6073 5437,7440 5441,6553 5446,4703 5450,7118 5453,6579 5455,5835 5457,5914 5462,4774 5463,8457 5467,7658 5472,7254 5474,7020 5479,6301 5481,8817 5485,9139 5488,6696 5492,5841 5496,8049 5500,6467 5505,5633 5509,5811 5514,7002 5516,5991 5521,9617 5524,8433 5527,10021 5529,8978 5531,8742 5533,8372 5536,5388 5540,9791 5544,7778 5546,6974 5551,7752 5555,7502 5556,5790 5561,10433 5562,9033 5566,7074 5571,8986 5576,9737 5577,9181 5582,8305 5583,9809 5586,4723 5588,8761 5591,8896 5592,8949 5596,6505 5598,5036 5603,7393 5604,5958 5609,9612 5611,10337 5615,8371 5616,8044 5619,9997 5623,5905 5627,7213 5629,9047 5630,9083 5634,4928 5635,5175 5640,9699 5644,8646 5648,8045 5652,8678 5655,4436 5659,6209 5663,9205 5665,5403 5669,10449 5672,4764 5676,4893 5681,9350 5686,10128 5689,6788 5690,7976 5695,7832 5696,9865 5699,7529 5704,8183 5708,4392 5713,6463 5718,7697 5721,10099 5726,5794 5728,9679 5732,6328 5734,9442 5739,8398 5742,4737 5747,5613 5749,10417 5753,10220 5754,4543 5758,8714 5761,7491 5766,8422 5768,7153 5771,7007 5773,7433 5776,9813 5778,6994 5779,4561 5781,4608 5784,6577 5788,6150 5791,6512 5793,10376 5798,10323 5802,8102 5807,5020 5810,7587 5815,10258 5820,4520 5821,5337 5824,8652 5825,8546 5827,7327 5828,10268 5831,9338 5835,6413 5838,8293 5841,10356 5844,6527 5845,5995 5848,8667 5850,10026 5851,6329 5853,6943 5857,7624 5861,4451 5863,8550 5864,8299 5865,7742 5870,6191 5872,5277 5877,4548 5878,7640 5879,9784 5883,10360 5885,7013 5886,8620 5890,9145 5894,10181 5896,9324 5901,4465 5902,9249 5905,4734 5910,5189 5912,6350 5917,7765 5920,10360 5921,9620 5926,7513 5927,7187 5928,9787 5931,10362 5934,7048 5939,7610 5943,9162 5947,6430 5951,8290 5953,4775 5956,6616 5958,8567 5959,7818 5960,8454 5962,8740 5964,8506 5969,7854 5974,5273 5977,10440 5982,7053 5986,8416 5990,7082 5994,5273 5997,7382 5999,6778 6004,7855 6007,5011 6009,6516 6011,8058 6016,7992 6018,7718 6021,10006 6025,6376 6028,5941 6029,8144 6030,6215 6035,7722 6040,9385 6043,4550 6048,10080 6049,8540 6053,8423 6054,8288 6059,9555 6061,5447 6064,6024 6066,10285 6068,8527 6070,6480 6072,8194 6074,8990 6075,4977 6076,8681 6077,10454 6079,5340 6081,7395 6084,4727 6088,9630 6090,4578 6093,10430 6094,5046 6097,9951 6101,8315 6105,8561 6107,8954 6111,6828 6113,8818 6115,5100 6117,6762 6119,4752 6120,7274 6123,5388 6125,7041 6128,4786 6130,5089 6133,9197 6137,5308 6142,7039 6145,7406 6146,6720 6151,10214 6155,7012 6157,9075 6162,7015 6166,8326 6171,8886 6176,7852 6179,7227 6182,7775 6183,6105 6185,9844 6189,8719 6191,6408 6192,5209 6193,5075 6198,10422 6202,9642 6207,5534 6210,10097 6214,7112 6219,8761 6223,5603 6224,9365 6225,7978 6228,5176 6232,7256 6234,7277 6237,5852 6238,9983 6239,10375 6240,6055 6245,9564 6246,5511 6250,5532 6254,5802 6255,7177 6256,5475 6257,7024 6258,5061 6262,5580 6267,7332 6269,7471 6272,7991 6273,7994 6275,8420 6280,4480 6281,9203 6285,6787 6288,9665 6289,10302 6293,5830 6298,9693 6303,9405 6304,9007 6305,6652 6306,7398 6307,9446 6309,8796 6311,4660 6313,5527 6317,9754 6322,4702 6326,10171 6330,6237 6331,6431 6335,8419 6337,6734 6339,4739 6340,8507 6342,4616 6345,6056 6348,5167 6349,10472 6351,9885 6355,9026 6356,8905 6357,8163 6361,4438 6363,4539 6368,5234 6370,9269 6375,8152 6379,5257 6382,9294 6385,6820 6387,4682 6391,6820 6392,9915 6397,5351 6399,4799 6402,8982 6403,8403 6407,8725 6410,8106 6412,9578 6417,10060 6418,6471 6423,4834 6426,10161 6429,9120 6433,4607 6434,8395 6439,8178 6440,9576 6445,9854 6449,6911 6453,10170 6455,8857 6457,9649 6461,7780 6466,10445 6469,6556 6470,8714 6474,7172 6479,8801 6484,6840 6488,4457 6490,7802 6494,6026 6495,5897 6500,7989 6501,4637 6506,9659 6507,5172 6511,9144 6516,7372 6520,5376 6522,7848 6526,9987 6530,5605 6535,5050 6540,8845 6541,5149 6542,5467 6543,5730 6548,4662 6550,10072 6553,6942 6554,5803 6556,6902 6559,4926 6562,5366 6565,8683 6566,4622 6571,9118 6572,6542 6577,6080 6581,9341 6585,10116 6588,8044 6593,4435 6595,5177 6597,10438 6602,9078 6607,4516 6608,10231 6611,10108 6613,7523 6615,6184 6618,7483 6620,6870 6625,9693 6627,5886 6628,6098 6630,9989 6633,4871 6634,8898 6635,8614 6636,8974 6639,9272 6644,9444 6645,4553 6647,5311 6651,10175 6655,4964 6659,8630 6661,9499 6664,7738 6665,6407 6670,9978 6674,6600 6676,10089 6681,6564 6683,9185 6686,7777 6691,6825 6695,7265 6696,7449 6701,6185 6706,8913 6711,6574 6712,5913 6713,9671 6717,4525 6719,8073 6721,7419 6722,8796 6723,7751 6724,5775 6726,8904 6730,9244 6731,5172 6735,7856 6736,5521 6737,6284 6742,8499 6743,6607 6748,4446 6749,6006 6753,7026 6758,8639 6762,6728 6763,9141 6768,10293 6770,8127 6775,4891 6779,8720 6783,5143 6784,9375 6786,9916 6790,5975 6794,10347 6798,8913 6800,10274 6801,6948 6806,8028 6809,5887 6813,5913 6818,9746 6819,10474 6820,4478 6824,8092 6827,9179 6828,4945 6832,6228 6833,10293 6835,5243 6837,6622 6842,8394 6844,6297 6845,6024 6850,6535 6851,5291 6855,4539 6860,10279 6865,5954 6869,5788 6872,5749 6877,7919 6879,8913 6880,6956 6881,8819 6884,6944 6889,7178 6894,8173 6899,7121 6903,7024 6906,8799 6908,9693 6909,6948 6910,9279 6912,8508 6914,6165 6919,10345 6920,9606 6922,8982 6925,7761 6928,6593 6933,8361 6935,9023 6940,6064 6944,6951 6949,6772 6952,9418 6955,4928 6960,7655 6965,9618 6967,8700 6972,8716 6974,8847 6975,10414 6978,5073 6980,10070 6985,8731 6989,6612 6991,6558 6992,6997 6996,7365 7000,6366 7004,6392 7006,5798 7011,10124 7015,9240 7018,5334 7019,8195 7021,10480 7025,9632 7026,7349 7027,8429 7029,4898 7030,7600 7031,7351 7033,5563 7034,4982 7037,4923 7039,5161 7042,8079 7045,9474 7046,5865 7051,9145 7054,9271 7059,5135 7061,7881 7062,10307 7064,9583 7065,4725 7068,10483 7069,9615 7074,6166 7076,8616 7080,6568 7081,8482 7082,6867 7083,8832 7085,8941 7090,5750 7092,4758 7097,4454 7099,10022 7102,6944 7105,7047 7108,6767 7112,4939 7117,10365 7118,4547 7120,10229 7124,8965 7129,7471 7134,9408 7138,4739 7142,9541 7143,10405 7146,6869 7150,5979 7155,7948 7158,8982 7159,7981 7163,7926 7168,10336 7169,6371 7170,7421 7171,10471 7176,9418 7181,9405 7182,4475 7185,9311 7190,7720 7195,4818 7197,4820 7202,8438 7204,5897 7206,6233 7208,4626 7210,8714 7211,5485 7215,7795 7216,7178 7221,5586 7222,8527 7224,8011 7225,4913 7230,9422 7231,9248 7234,7298 7236,7441 7241,7223 7243,4769 7247,8100 7252,5656 7255,6399 7256,6300 7257,8437 7259,10299 7262,7298 7263,7843 7267,9369 7268,5378 7273,5709 7278,9816 7281,10146 7284,8048 7287,9488 7289,10062 7291,7286 7293,8572 7295,7725 7298,7026 7299,4411 7302,9838 7307,10210 7309,4483 7313,9694 7316,9713 7318,9515 7320,5838 7323,9258 7325,8200 7327,7203 7330,6423 7332,8624 7337,7203 7341,4852 7345,7111 7347,6848 7350,4438 7355,6581 7359,4619 7362,8979 7363,9114 7364,8268 7366,9217 7370,6831 7375,8677 7380,7067 7382,5086 7386,8314 7391,10473 7395,4483 7398,10467 7401,6093 7403,8539 7404,9211 7409,9084 7414,5419 7418,9449 7423,8347 7425,6136 7426,5637 7427,9964 7429,10484 7432,7370 7436,7771 7440,7462 7443,8700 7446,8945 7450,9845 7454,9556 7459,9878 7464,9397 7466,9980 7471,4615 7475,10447 7476,8491 7477,7481 7482,5939 7487,10028 7490,10385 7493,9873 7498,9768 7501,8188 7502,4383 7507,7101 7509,9497 7511,4520 7516,4412 7519,8926 7522,6616 7523,6763 7525,5387 7530,8008 7532,9407 7537,8624 7539,6341 7540,6517 7544,7055 7545,8562 7547,6179 7550,7348 7553,8548 7555,9532 7560,8528 7561,5350 7565,6001 7567,9046 7570,8042 7572,8485 7577,8162 7582,5820 7583,7687 7587,8317 7588,10390 7593,8299 7594,5802 7598,8112 7601,8643 7606,6305 7610,7466 7613,7047 7618,6646 7622,10348 7624,6164 7625,5046 7627,5675 7628,8742 7633,5038 7638,8869 7639,7387 7643,6298 7646,5364 7650,4597 7655,5298 7660,8599 7662,9436 7663,5145 7667,6664 7672,8674 7677,6649 7679,4845 7681,8251 7686,9867 7691,8642 7696,10016 7701,8921 7703,5770 7708,6681 7712,7181 7714,4834 7717,8179 7722,10213 7725,7480 7727,10170 7731,4689 7735,7507 7739,5858 7744,9393 7747,8334 7749,5361 7750,5977 7754,6392 7758,5732 7761,6884 7762,4633 7766,8677 7771,9863 7774,8089 7775,9554 7778,9703 7780,5879 7783,4382 7784,6212 7787,7352 7792,5014 7797,10203 7801,9529 7804,8458 7806,9723 7807,9957 7808,7548 7809,6750 7813,6647 7818,9811 7823,5025 7827,6118 7828,9422 7831,7885 7832,10206 7834,6801 7839,9868 7841,8769 7842,7439 7847,10480 7850,10176 7854,9749 7859,10067 7862,5878 7863,5775 7865,9501 7866,6923 7869,4949 7871,5079 7875,8670 7879,4489 7883,4826 7884,7427 7885,8590 7887,7088 7891,7626 7893,6994 7896,9354 7899,4591 7900,5854 7902,8661 7904,6257 7905,8304 7906,6797 7911,10475 7915,4958 7918,7832 7920,6819 7923,8019 7924,8072 7926,9503 7927,8812 7929,7422 7933,7321 7934,5269 7939,6336 7942,4825 7944,8704 7948,5456 7949,8561 7952,9045 7955,7675 7960,8426 7962,7636 7965,7988 7969,9747 7973,9746 7976,9606 7979,7836 7984,5491 7987,4672 7992,5345 7996,5799 7997,9687 8000,8772 8005,5294 8010,9353 8013,8814 8015,5112 8016,7833 8020,4539 8022,7692 8027,8576 8032,7164 8033,9840 8036,7454 8038,8940 8041,6656 8045,8737 8048,10254 8049,8674 8054,10213 8059,9516 8060,4848 8065,10090 8067,9584 8070,5371 8072,4988 8074,4862 8079,10407 8080,7885 8082,5006 8085,4710 8090,4833 8091,7920 8092,8508 8097,6553 8102,9676 8103,8210 8104,6749 8108,7192 8111,5416 8112,6150 8116,10058 8120,5459 8122,5668 8125,7006 8126,8479 8130,5842 8135,7496 8140,6690 8141,5530 8142,5015 8143,7667 8146,8518 8147,7320 8149,8129 8151,9799 8154,8884 8159,9349 8160,6305 8162,7599 8165,7388 8169,6580 8170,7424 8175,7703 8180,5473 8184,8246 8187,6618 8191,5851 8196,9619 8200,9867 8205,7773 8209,6365 8214,7076 8218,8101 8221,7284 8225,9644 8226,4471 8229,8690 8230,4708 8232,4699 8234,6095 8237,4675 8242,4675 8244,7842 8245,6258 8249,6915 8254,6821 8259,6631 8260,10184 8263,7339 8267,5345 8271,5475 8275,8814 8277,6268 8281,5245 8283,5420 8286,4981 8288,8091 8290,4576 8295,9402 8297,5445 8299,10052 8300,5625 8304,6887 8309,5508 8310,5401 8312,7403 8313,5341 8318,6156 8321,8103 8323,7018 8328,5509 8329,5982 8333,8897 8334,9211 8337,10019 8341,10069 8343,8059 8348,10126 8352,5784 8357,8196 8360,9184 8361,10403 8363,6061 8364,5102 8368,7896 8370,10439 8372,8504 8373,6358 8374,10417 8377,5964 8380,4551 8382,8002 8384,4900 8387,8481 8391,6314 8395,9565 8396,5707 8400,6857 8401,7107 8402,9829 8405,5646 8409,5222 8410,5554 8412,9262 8413,6332 8415,9398 8416,9696 8418,7446 8423,5915 8425,6284 8430,4529 8431,6224 8433,8552 8436,7160 8441,5898 8443,5771 8447,8891 8451,7151 8455,8093 8458,5357 8462,7464 8466,6598 8470,8731 8473,7009 8478,9696 8481,5806 8484,4781 8489,10376 8493,9895 8497,10070 8500,7451 8502,9636 8507,8702 8512,5625 8517,4443 8522,5560 8527,6564 8529,5072 8530,8041 8533,8712 8534,10419 8537,8148 8542,7082 8545,10057 8550,8472 8554,6550 8555,6082 8556,9397 8559,5832 8560,8345 8565,9287 8569,8394 8570,9906 8573,9783 8577,9308 8581,8053 8584,10217 8586,4857 8588,7638 8589,5439 8594,7424 8598,10267 8602,5649 8606,5127 8607,4828 8608,7115 8611,5584 8614,7455 8619,4999 8623,7187 8628,7222 8631,9587 8632,5674 8636,9079 8638,8260 8641,9521 8642,9534 8643,4652 8648,9212 8653,6858 8656,5048 8660,4579 8664,7172 8668,8630 8672,6403 8676,7867 8679,9951 8681,10017 8685,6482 8687,10058 8692,8157 8693,7206 8698,9863 8699,6903 8704,4721 8705,5970 8709,10461 8710,7870 8711,9864 8716,9482 8721,6437 8726,7492 8727,8267 8732,7972 8733,8509 8735,9474 8737,8902 8740,10231 8741,8271 8746,5238 8747,7851 8749,9855 8754,4604 8756,8067 8760,4574 8762,7373 8766,7620 8770,7072 8772,4827 8777,4537 8778,4393 8780,4931 8783,8393 8788,7667 8791,7295 8792,4735 8793,6219 8795,10404 8796,7733 8800,4801 8801,9331 8802,9529 8805,6588 8810,8331 8815,10442 8818,6945 8823,6200 8824,9452 8827,8908 8830,8435 8835,4489 8836,5675 8837,4961 8840,5821 8842,9131 8846,6109 8849,7203 8853,8319 8857,8065 8860,7342 8861,9257 8865,8646 8869,4767 8874,4700 8875,6220 8878,6490 8882,5787 8887,8254 8889,8148 8892,6850 8895,7039 8898,7753 8901,6243 8903,10093 8908,9920 8913,8108 8918,7770 8922,10362 8926,7662 8927,7137 8931,7635 8933,5851 8938,7924 8941,7928 8945,9571 8947,7121 8949,5579 8953,6228 8954,4650 8955,9941 8957,9925 8960,8172 8965,8114 8967,5953 8968,7220 8971,7480 8972,10284 8976,9490 8977,7771 8982,5484 8987,5402 8992,5273 8993,6496 8997,8704 9002,5089 9003,8824 9007,4581 9008,4641 9013,9355 9014,7345 9018,8369 9022,7585 9026,9456 9031,7040 9036,6568 9040,9991 9045,7033 9047,8060 9048,8242 9050,8564 9053,7867 9055,10169 9058,5046 9059,5173 9060,9886 9062,4979 9066,4587 9070,6060 9072,8464 9077,5185 9082,8480 9083,9672 9085,7985 9089,10297 9092,7553 9094,5673 9096,10172 9097,10153 9099,9426 9104,7614 9107,9078 9110,8845 9111,10386 9115,6131 9118,8100 9122,4825 9123,4722 9126,9472 9130,4581 9134,6545 9139,5117 9140,6888 9145,7180 9147,5654 9151,9926 9155,8914 9158,5623 9163,5316 9167,8993 9168,10481 9172,8929 9175,4475 9176,7672 9178,9284 9181,9354 9186,10071 9188,8484 9191,4752 9196,7815 9201,6815 9203,4508 9207,10296 9212,6779 9216,10108 9219,6396 9220,8566 9224,9841 9228,4565 9233,7541 9236,8964 9240,8892 9241,5754 9245,9684 9250,7974 9254,9159 9257,5263 9259,4783 9260,10097 9263,5176 9265,6314 9267,5382 9271,7737 9275,9571 9276,5722 9281,9737 9285,5816 9288,8840 9290,5667 9294,7049 9298,9896 9303,4994 9308,4691 9311,5783 9313,5050 9318,7494 9322,4613 9324,7842 9327,5869 9330,6844 9335,8435 9339,7146 9343,5130 9347,9433 9352,7148 9357,6380 9359,8270 9360,9315 9363,8825 9365,4599 9369,6885 9373,7964 9378,7607 9380,7684 9383,7350 9386,9599 9387,6447 9391,6802 9394,5231 9395,8769 9398,7032 9402,5775 9403,6200 9408,8476 9413,5697 9418,6469 9422,9777 9423,10437 9428,10068 9430,10024 9432,7184 9434,10002 9436,8642 9440,4481 9443,8080 9444,8505 9449,6103 9454,7400 9459,5101 9464,9628 9466,5182 9469,8073 9472,9448 9476,6739 9478,6394 9483,8610 9485,8723 9490,9381 9491,8427 9494,7670 9496,10300 9500,6901 9502,8462 9503,6304 9508,4616 9512,5640 9516,6843 9517,5711 9522,6536 9524,6328 9526,4995 9531,5074 9534,6823 9539,10062 9544,9911 9546,9879 9550,8826 9555,10090 9557,6028 9560,7552 9564,9801 9569,5727 9573,7243 9578,7275 9581,6389 9582,6958 9587,5375 9590,5675 9591,6398 9596,6054 9599,7843 9603,6985 9607,7977 9612,9133 9614,6374 9618,7379 9623,9673 9628,7784 9633,4653 9634,5973 9639,8661 9641,8649 9646,4648 9648,9144 9651,9673 9656,10399 9657,4870 9662,5531 9664,7564 9665,6317 9667,6785 9671,5547 9673,10428 9676,9091 9681,7439 9686,5816 9687,6127 9690,7285 9693,8441 9696,10442 9701,7845 9703,7114 9704,5884 9706,4525 9707,9435 9710,8813 9712,8312 9717,8972 9718,10114 9719,7119 9720,7097 9723,4556 9726,6795 9728,9650 9733,7770 9738,4891 9743,10386 9746,8104 9750,8937 9755,9963 9757,5701 9758,8377 9761,6698 9762,7036 9765,6767 9769,6068 9771,9988 9776,9910 9779,7305 9783,9345 9786,5106 9789,8232 9792,10141 9794,7180 9795,5333 9797,5266 9802,9306 9805,5840 9810,7540 9814,8069 9818,6457 9820,4875 9821,8180 9822,5464 9825,5255 9830,9653 9832,9607 9836,4875 9839,6354 9841,9983 9843,4608 9847,9341 9851,8217 9855,9102 9860,8824 9865,10425 9869,6894 9870,7098 9873,9288 9876,8166 9877,8290 9880,8730 9883,7621 9888,5650 9889,6856 9890,4753 9891,7483 9896,10318 9898,7699 9901,8222 9903,10286 9905,9082 9907,5401 9911,10437 9916,4546 9918,6980 9921,9817 9925,7941 9930,6151 9931,4515 9933,8383 9938,6980 9939,6604 9941,9583 9946,4389 9947,6286 9948,6117 9953,6665 9957,9001 9959,6042 9964,7442 9969,7576 9973,10037 9976,4936 9978,8151 9981,5067 9985,6442 9989,6757 9991,8221 9996,8916 9998,5054 10000,6276 10002,9529 10005,8481 10009,7435 10011,9704 10015,4378 10019,7950 10020,5172 10025,8486 10028,9172 10029,7820 10033,9740 10037,7681 10038,8707 10042,5250 10045,8211 10047,7946 10049,10308 10054,5961 10059,5625 10060,6666 10065,5448 10068,9217 10071,6948 10076,5186 10080,8390 10083,6812 10084,8102 10087,9271 10091,8094 10092,5780 10097,4464 10098,4846 10100,5006 10104,5540 10105,10146 10109,8864 10113,8800 10117,7377 10120,7768 10122,10109 10125,7060 10128,9340 10131,7894 10132,7783 10134,9425 10138,6247 10143,5236 10144,9208 10147,7238 10149,9891 10151,7549 10152,9590 10154,8227 10156,5091 10160,10433 10163,7353 10168,6390 10169,10022 10170,5958 10173,7379 10177,4963 10179,6124 10184,10105 10186,6110 10190,7661 10192,5023 10194,9699 10196,6960 10199,9088 10203,6509 10206,4861 10211,9479 10214,5682 10219,8039 10220,8012 10224,6946 10225,6213 10228,5089 10229,9547 10233,6450 10237,7629 10239,8100 10242,6301 10246,9232 10248,9816 10253,8345 10254,7698 10259,6763 10264,6750 10267,7947 10270,4445 10271,7710 10275,8782 10278,6136 10283,9628 10287,4430 10289,6897 10293,9944 10295,4915 10299,9815 10301,4741 10305,9278 10310,6596 10311,9717 10315,4593 10319,5344 10321,8432 10324,7666 10325,9039 10329,7709 10330,5854 10331,10159 10334,7873 10338,4805 10343,8548 10346,4956 10348,5241 10352,10348 10355,5020 10358,8420 10360,8443 10362,6238 10366,10029 10367,9957 10370,10026 10375,6019 10377,4501 10381,6461 10384,5836 10386,4723 10388,8538 10389,9444 10390,6637 10393,5077 10396,7750 10400,8850 10402,6953 10404,10445 10405,7590 10408,6501 10412,8161 10416,10210 10418,9884 10419,5733 10424,5069 10429,4432 10433,5583 10438,5145 10442,6531 10445,6314 10448,6805 10453,7775 10454,5481 10456,5512 10457,8889 10459,9256 10460,8585 10462,7584 10467,4643 10471,9488 10476,8491 10477,8389 10481,6419 10482,4869 10486,9488 10489,8716 10494,9523 10499,9551 10504,6937 10505,5009 10510,9526 10512,7766 10514,9769 10517,5977 10518,5601 10519,10197 10521,7781 10525,5006 10528,7445 10529,7643 10530,8107 10533,9153 10536,7813 10541,4503 10546,6374 10551,5351 10554,4398 10555,5484 10557,4655 10559,7922 10564,8131 10567,6667 10572,7456 10573,8034 10578,6879 10581,6110 10582,7162 10585,4900 10590,10373 10591,4516 10592,10282 10594,10313 10599,9909 10600,8691 10603,9755 10608,4546 10612,5971 10616,7639 10617,8613 10618,9871 10620,9909 10623,9605 10626,6231 10629,7606 10631,4404 10634,4518 10639,8905 10642,8102 10644,4536 10646,9056 10650,5576 10653,7608 10657,5295 10660,9351 10663,6823 10665,4507 10667,7010 10669,8030 10674,7118 10677,7230 10680,7276 10682,4969 10685,9827 10689,6322 10693,5178 10698,6183 10702,8895 10704,7647 10707,8009 10711,7586 10715,7185 10718,4708 10720,8781 10722,7689 10727,9304 10729,6770 10731,9810 10732,8345 10733,7254 10737,5582 10739,7535 10744,8713 10745,8913 10750,4821 10754,5376 10758,9457 10761,5054 10764,8255 10766,6298 10767,5249 10768,7987 10773,4433 10775,8177 10776,9175 10777,5387 10779,4452 10784,8375 10789,8237 10791,7045 10794,6765 10799,5677 10802,6199 10807,6910 10812,9974 10817,10456 10821,5116 10823,8479 10826,9870 10828,8133 10831,6500 10833,9371 10835,9309 10840,9359 10843,7624 10846,5513 10848,9946 10851,5017 10855,5449 10858,4481 10862,5013 10866,4973 10868,4508 10872,8658 10873,5511 10874,4606 10878,6904 10880,6115 10884,5297 10887,5944 10891,7603 10896,8956 10897,4650 10902,5886 10907,10042 10911,4898 10914,7278 10918,8485 10922,8673 10925,9850 10930,8966 10932,5194 10934,5732 10939,7850 10942,10322 10947,4640 10950,8988 10951,4647 10955,6377 10959,4896 10963,5028 10965,4377 10970,7291 10974,5007 10976,6178 10978,10056 10981,7457 10984,9805 10988,9596 10991,4784 10994,7933 10998,8101 11001,4669 11005,9356 11006,5708 11008,4382 11012,7643 11013,4384 11017,5500 11021,6990 11022,10438 11023,6267 11028,5065 11033,9648 11038,8258 11042,8752 11044,7012 11046,8948 11051,9871 11056,6572 11060,5067 11064,6652 11065,4869 11070,5608 11073,6243 11077,5374 11078,7933 11082,9493 11086,8054 11090,9134 11091,5725 11096,9315 11097,6520 11098,9559 11099,9285 11100,5528 11101,4939 11106,8895 11107,9299 11110,9177 11115,6082 11116,4934 11117,8491 11122,9878 11123,7035 11127,9012 11130,8547 11134,4566 11135,7727 11138,5487 11139,7859 11142,4671 11143,9791 11145,8817 11148,6745 11150,7323 11155,7240 11160,8270 11165,8377 11170,9951 11173,9940 11174,10118 11179,9143 11180,7669 11182,10259 11183,7147 11188,9279 11190,4551 11194,5689 11198,9140 11200,4462 11204,8414 11209,5457 11212,6310 11216,7876 11221,4418 11223,6988 11226,9802 11231,5723 11236,9983 11238,8990 11242,9778 11243,7994 11245,5860 11249,8038 11253,4922 11258,9726 11260,5579 11261,8013 11263,6753 11267,8853 11270,6207 11273,6892 11277,8274 11280,6493 11281,8183 11284,5702 11288,4660 11290,8540 11294,7743 11296,7206 11298,7731 11302,9566 11303,8313 11305,9298 11306,9854 11308,6237 11313,7251 11316,10148 11320,7843 11322,9051 11327,9129 11331,8769 11333,9502 11335,6325 11337,5788 11338,9564 11340,5464 11345,7684 11348,10265 11350,5964 11353,4674 11358,9495 11359,10291 11361,8388 11365,4538 11367,5655 11369,5728 11374,9182 11378,10130 11379,6623 11380,7503 11382,9908 11383,9710 11384,8039 11385,9292 11387,9555 11391,7416 11392,5565 11393,5573 11396,6579 11401,6633 11405,7061 11410,9685 11413,4881 11418,5678 11421,10028 11426,6204 11427,8276 11430,9702 11434,5923 11435,7477 11440,7416 11442,7746 11447,10218 11450,4712 11455,9382 11458,10127 11459,4435 11463,8612 11468,8729 11469,9830 11473,5908 11477,6554 11481,7732 11483,10002 11485,9631 11486,7213 11489,5053 11491,7112 11494,8163 11498,8375 11502,6667 11505,4696 11508,8351 11509,5139 11511,8136 11513,8225 11515,4926 11520,9287 11525,6586 11530,5859 11532,7545 11535,8997 11540,9930 11545,9383 11548,9971 11551,7141 11555,8824 11557,10154 11560,5239 11561,4880 11564,10257 11567,9949 11568,6394 11573,9262 11576,9421 11577,8874 11582,8594 11587,8729 11591,8702 11596,6765 11598,4484 11599,5813 11600,9181 11603,9296 11605,10372 11606,5941 11608,7648 11612,7622 11616,9963 11621,10033 11624,6146 11625,5816 11629,9579 11632,7435 11636,5341 11638,10182 11642,8865 11647,10131 11652,4708 11656,5361 11659,9254 11663,9105 11665,4777 11667,4788 11671,8463 11675,7979 11676,4659 11679,10435 11680,8192 11684,7424 11687,5867 11688,9735 11691,7155 11696,5985 11699,9996 11702,10026 11704,5096 11707,8298 11712,7001 11714,9190 11719,6375 11721,5462 11724,8459 11726,5399 11728,4989 11730,5534 11732,9015 11736,8617 11738,5133 11742,8285 11746,9489 11748,8864 11752,6360 11755,9399 11757,8335 11759,4665 11761,10288 11766,7225 11769,4541 11772,6509 11773,9415 11774,7226 11775,4675 11777,8491 11780,4782 11784,10415 11788,9321 11790,4917 11792,4444 11797,8345 11801,6203 11805,7041 11806,5867 11809,4468 11813,6754 11817,5796 11822,10237 11826,7450 11831,9675 11836,5174 11837,9800 11842,4978 11846,6450 11849,6053 11852,4588 11857,9042 11858,6742 11862,8434 11864,7868 11866,7028 11869,6845 11871,8972 11875,5063 11879,10184 11884,4692 11887,7521 11892,7150 11897,5879 11900,4882 11904,7016 11905,5061 11910,9763 11912,9725 11915,7796 11916,6115 11921,8468 11923,5935 11926,5457 11930,4506 11932,5533 11934,9722 11935,5797 11937,9573 11939,8237 11943,5219 11946,9085 11951,5410 11952,10420 11956,5301 11961,8195 11966,7702 11969,7748 11970,7154 11974,5337 11975,6125 11980,6096 11985,4863 11990,4571 11991,9638 11992,8333 11995,7345 11996,9311 12000,7950 12002,6753 12005,9641 12008,9570 12010,6147 12015,10005 12019,8064 12021,9224 12024,9047 12027,9385 12028,8357 12030,5165 12034,9307 12038,7220 12043,7791 12045,4805 12050,5383 12054,4417 12055,4430 12059,5075 12062,8836 12063,6069 12064,10185 12069,6528 12070,5081 12073,5877 12078,4546 12079,6946 12081,8917 12082,4911 12085,6668 12086,6585 12087,6582 12089,7805 12092,7776 12096,5990 12099,4412 12101,6576 12103,6589 12107,5430 12112,8096 12116,7967 12118,4510 12119,8960 12123,10143 12124,4492 12126,9175 12131,9158 12132,5450 12134,6040 12135,9351 12140,8054 12144,7578 12146,10465 12147,9269 12150,5459 12151,6099 12156,10126 12160,6096 12163,9066 12165,5946 12167,10432 12172,5237 12176,8495 12178,5919 12181,5038 12185,6513 12190,7312 12194,6654 12198,9653 12201,8155 12203,7104 12205,5339 12210,6429 12215,6655 12216,4667 12220,5259 12221,8492 12223,9204 12227,7935 12230,6392 12233,4807 12238,8247 12239,6353 12243,8790 12248,7002 12251,6099 12256,6657 12259,7848 12263,8212 12266,10199 12267,7640 12270,8806 12274,10196 12278,5502 12283,8506 12286,9501 12290,6244 12293,7050 12296,7986 12297,9703 12298,4847 12303,10309 12304,4452 12308,6389 12312,10362 12313,6646 12317,8037 12322,4457 12326,9156 12329,9604 12332,7880 12336,9903 12337,9875 12342,9812 12345,5009 12350,7951 12354,9754 12355,8878 12357,6787 12361,8938 12365,6876 12370,8470 12374,7636 12375,5045 12379,7567 12380,10158 12384,9149 12386,4482 12390,9645 12395,7137 12400,6220 12404,6891 12405,9706 12409,4979 12412,5238 12415,8525 12416,5499 12420,10215 12421,7440 12424,7373 12427,10017 12428,9205 12433,8373 12436,4433 12438,5173 12439,9740 12443,5381 12445,6918 12449,8653 12453,9120 12456,7731 12458,10293 12459,5320 12462,8971 12464,9310 12469,6295 12470,8951 12471,5310 12475,8949 12477,10455 12478,9105 12483,6046 12484,6342 12489,9860 12492,9932 12496,5825 12501,4384 12503,9235 12504,9169 12509,7132 12514,9919 12517,8515 12522,9188 12527,8766 12529,6447 12532,7988 12533,10316 12538,8078 12542,9771 12547,5051 12552,9141 12554,6149 12557,6951 12559,4775 12561,8255 12565,9273 12570,5519 12575,9493 12578,9449 12580,4974 12584,9735 12589,9039 12593,6371 12594,10263 12596,8616 12600,6788 12603,9517 12604,5966 12605,5381 12609,4977 12611,5156 12612,5253 12617,5210 12619,8335 12623,7112 12628,10260 12631,9899 12636,8978 12638,6703 12639,4586 12644,5047 12645,5020 12650,4450 12653,9715 12658,6984 12663,9976 12667,8064 12670,6830 12671,9143 12676,9901 12681,8872 12684,5277 12688,7085 12693,7732 12698,8361 12702,5649 12705,7583 12709,9169 12710,9702 12712,8936 12717,7221 12721,9939 12726,9154 12730,4961 12733,9682 12736,5211 12737,7478 12738,9568 12740,10324 12743,6930 12745,9481 12746,7449 12750,5494 12755,6346 12756,5709 12759,9356 12762,9632 12766,6388 12771,5746 12776,7141 12777,6345 12778,8071 12783,8009 12785,7568 12788,9333 12789,5117 12792,7993 12796,5045 12798,6427 12800,8175 12803,8613 12805,8605 12810,5156 12813,9378 12814,5770 12815,8280 12818,6967 12823,4680 12824,7538 12828,6338 12833,4754 12836,9226 12838,6590 12839,4476 12840,10040 12844,9522 12849,5840 12852,8318 12854,7248 12855,6254 12860,10468 12861,8525 12866,5232 12867,8063 12869,6419 12874,8820 12878,10442 12882,5863 12885,5700 12888,5755 12890,7109 12893,7976 12895,7829 12900,7105 12904,5792 12906,7652 12909,7318 12913,10208 12917,6782 12918,6367 12920,5360 12921,6476 12924,5757 12926,5917 12928,10107 12929,7067 12934,9366 12935,8989 12937,7429 12940,10472 12942,8622 12944,6016 12948,5181 12949,5203 12951,6178 12954,8720 12959,8615 12964,5001 12966,4731 12970,6275 12972,4574 12975,10357 12979,7776 12983,8804 12985,6834 12986,7217 12989,8615 12990,9407 12992,8066 12995,7249 12999,6627 13004,8074 13008,6256 13011,8381 13013,9278 13017,6716 13022,9617 13026,10289 13029,7393 13032,6455 13036,7637 13041,9703 13042,5528 13047,7386 13050,9064 13053,6884 13058,8908 13060,6489 13062,7464 13067,10204 13068,9055 13072,6381 13076,9548 13079,8714 13081,8529 13085,4917 13089,9686 13093,7017 13097,6492 13100,8664 13105,9221 13110,7080 13115,9977 13119,8918 13121,5938 13125,6604 13126,10098 13131,10306 13133,7234 13135,10398 13136,10191 13138,9458 13142,8659 13144,4596 13147,10275 13150,5488 13154,8773 13156,9663 13159,9737 13160,8850 13164,7322 13169,7772 13170,9770 13175,9939 13179,10308 13182,6281 13187,9633 13190,5491 13194,10255 13198,9906 13201,6556 13202,7403 13205,4974 13206,9601 13210,5692 13214,9092 13216,8026 13221,4901 13224,5633 13227,5232 13229,8617 13234,6894 13239,9250 13242,8970 13246,7636 13251,8406 13254,5819 13259,8278 13261,5698 13262,8241 13267,7787 13272,8086 13277,6361 13282,6434 13285,6910 13289,4716 13292,5638 13295,10337 13298,7835 13303,9838 13308,9935 13313,5898 13315,5869 13318,6518 13320,4815 13323,10284 13328,8813 13329,9921 13332,9677 13335,9270 13339,4964 13340,4392 13344,8445 13349,10306 13350,6685 13351,9288 13355,5205 13357,9946 13362,7335 13364,9501 13367,7914 13372,5905 13377,7621 13382,5815 13384,8132 13386,9737 13387,7361 13389,8828 13392,8119 13397,9707 13402,5943 13406,10313 13408,7340 13412,8381 13414,8762 13419,9632 13421,10415 13425,6970 13428,6853 13430,7245 13432,5439 13437,4898 13440,7910 13442,6096 13447,8024 13451,7514 13452,9845 13453,6370 13457,8021 13461,10306 13465,4570 13468,8563 13469,5819 13471,8447 13475,10207 13480,7905 13481,8679 13485,7805 13488,10070 13493,8626 13497,9334 13498,6275 13500,7069 13501,10107 13506,5583 13507,8254 13511,6974 13514,6381 13518,8193 13522,4518 13523,5663 13527,5455 13528,8276 13531,6516 13536,7625 13539,10487 13543,6625 13545,9099 13548,8777 13552,8779 13553,5888 13554,9538 13559,7574 13563,8674 13566,5202 13570,8191 13574,9499 13575,4769 13577,8503 13581,4958 13585,6552 13589,5251 13590,9503 13591,6994 13595,10452 13600,7154 13602,5278 13603,5238 13605,4789 13610,6810 13614,6917 13619,5508 13622,4523 13625,7371 13630,6991 13634,6765 13635,4986 13637,6945 13639,9632 13641,8788 13642,7129 13647,4589 13650,6082 13652,5721 13656,8381 13661,4901 13665,6607 13667,9204 13672,6667 13673,5166 13674,5011 13679,5007 13683,6992 13685,4558 13686,6873 13691,8188 13696,4847 13699,8717 13702,7726 13706,8507 13709,8007 13713,9730 13714,7790 13716,5489 13718,7981 13721,4382 13722,7192 13726,8800 13728,7659 13730,7738 13735,9820 13737,6349 13740,10279 13745,8272 13749,6751 13752,7390 13753,9801 13758,5207 13759,8515 13761,6556 13764,5512 13768,9101 13769,4871 13770,5858 13774,9599 13777,10292 13781,4798 13783,10340 13786,4520 13788,8919 13790,7317 13793,5070 13798,6081 13802,7881 13807,5055 13808,6754 13809,6760 13814,4440 13819,7683 13822,8642 13823,4647 13828,8793 13833,5042 13838,4730 13843,9305 13847,5534 13851,7612 13855,6073 13856,9811 13857,8859 13862,10292 13863,7147 13865,7728 13868,9338 13873,7425 13875,5516 13877,9296 13881,7315 13884,7632 13887,6252 13888,9768 13893,10416 13895,8348 13897,10137 13902,8736 13907,6851 13908,8832 13913,10250 13918,7832 13921,9090 13925,6048 13926,8152 13930,8333 13935,7331 13940,7611 13942,5584 13946,10439 13949,4477 13952,8748 13957,5969 13959,7679 13961,9286 13963,5411 13968,5884 13971,4655 13972,9845 13976,7034 13981,10136 13986,10335 13988,6893 13992,5559 13995,9581 14000,8658 14005,9538 14010,9630 14013,9545 14018,7846 14020,7100 14023,5218 14026,6044 14031,5090 14035,5392 14040,6130 14043,8069 14045,10011 14049,7172 14051,4612 14056,7832 14060,5542 14065,7450 14067,6465 14071,7073 14075,7057 14079,8519 14083,9657 14085,6966 14087,7625 14091,8717 14093,6789 14094,5500 14098,6735 14099,9207 14102,8945 14105,8662 14106,8439 14110,9738 14115,7331 14116,4749 14118,6634 14122,8409 14127,9844 14128,6518 14133,5469 14138,9301 14141,6451 14145,4891 14146,5921 14148,7588 14149,9784 14152,8675 14155,8181 14157,5773 14162,7330 14165,4529 14166,9137 14168,5876 14169,9943 14172,6995 14173,8069 14175,7143 14179,8200 14181,9711 14186,9102 14188,7956 14192,7506 14196,5268 14197,7407 14202,10341 14205,4453 14206,7065 14208,6305 14211,7335 14214,4702 14217,8032 14220,7369 14221,6245 14225,8151 14229,8993 14230,7641 14233,7834 14236,6069 14239,7497 14241,8216 14242,4886 14247,5268 14251,7471 14253,9817 14258,6215 14262,5091 14265,7897 14268,6331 14269,6614 14271,8946 14274,9011 14276,6543 14280,5993 14283,6279 14286,8049 14288,9996 14290,6182 14294,7217 14296,6658 14298,7795 14300,5108 14302,8343 14306,9916 14310,8322 14314,4576 14317,10236 14318,7829 14323,5938 14324,8889 14328,7338 14333,5461 14337,9335 14339,6620 14341,5181 14346,10159 14348,8810 14352,7704 14355,4510 14360,9491 14363,4593 14368,10489 14372,8225 14376,7184 14380,8443 14381,8597 14382,9099 14387,4749 14392,5688 14394,8802 14395,6532 14397,6014 14398,6688 14399,7059 14404,8863 14407,9643 14408,5922 14410,8256 14415,5624 14418,5648 14419,5051 14420,8916 14424,5547 14428,6038 14433,9706 14438,10082 14442,6203 14447,8192 14450,7444 14455,9994 14456,8078 14460,7250 14464,4695 14467,6083 14468,5721 14472,8236 14476,4551 14478,5294 14482,7405 14486,6539 14487,9933 14488,8207 14490,4395 14494,7720 14495,5925 14498,8541 14501,6437 14506,9043 14508,6797 14513,6524 14517,10110 14519,5486 14521,6141 14524,7077 14529,6648 14534,8244 14536,4633 14540,5303 14543,10452 14547,9871 14551,8668 14553,10026 14558,10484 14563,8690 14568,6443 14573,4397 14576,5582 14577,7336 14582,4524 14583,10007 14585,5397 14588,8956 14591,9004 14593,8547 14596,10449 14600,10408 14601,6027 14602,9501 14604,9377 14609,5392 14613,8044 14616,4733 14621,4753 14626,7680 14631,5039 14632,9501 14635,9645 14636,7839 14637,5340 14638,6332 14642,4567 14647,9495 14652,9994 14657,6438 14660,5125 14661,9095 14662,8101 14665,9364 14668,8960 14670,7531 14672,4741 14677,8091 14680,10436 14685,4635 14687,8595 14692,6737 14697,5582 14702,9967 14706,4597 14708,5367 14711,6923 14712,7294 14716,5138 14720,7511 14725,7424 14730,9539 14734,8623 14737,8222 14739,9794 14741,10014 14746,8757 14747,4988 14749,10297 14754,5730 14759,10181 14761,6789 14762,6386 14767,6488 14769,5582 14774,6966 14778,5532 14780,9556 14781,9452 14785,8010 14788,5979 14791,6211 14796,4971 14798,5300 14799,7260 14802,10315 14806,4818 14808,6480 14811,6390 14813,4991 14816,5709 14819,6937 14823,7365 14828,4906 14829,9793 14830,5176 14831,7413 14835,6441 14839,4446 14844,5939 14846,10161 14850,7324 14851,7755 14854,7116 14856,5194 14861,8688 14862,9643 14866,5151 14869,4497 14871,4380 14873,5774 14877,7948 14882,8239 14887,9171 14891,8871 14896,9091 14897,6841 14901,9910 14903,5712 14906,9842 14909,4496 14912,7719 14915,6608 14920,7365 14922,9198 14923,9777 14926,8462 14930,5746 14933,5612 14938,10167 14942,7655 14947,8486 14949,6290 14951,6642 14953,7182 14955,8997 14959,6027 14963,8636 14967,6824 14970,9087 14973,5236 14975,6958 14980,6859 14982,9076 14984,10022 14989,9223 14993,8976 14994,10083 14998,6094 15001,4485 15003,7824 15008,6525 15010,6699 15012,9208 15016,8732 15017,4788 15018,9640 15022,9591 15026,7245 15030,7545 15032,6638 15036,8713 15039,8210 15044,7235 15048,7321 15052,5923 15056,9093 15059,7901 15064,9395 15065,10248 15070,5202 15072,7667 15076,5238 15079,9850 15084,9831 15086,8211 15087,10203 15091,9924 15093,7377 15098,5493 15102,9228 15106,9697 15107,6946 15109,9467 15113,8378 15116,9318 15119,10203 15120,8687 15122,10092 15125,7463 15128,4759 15130,6983 15134,5804 15135,8938 15136,7869 15137,10265 15142,4946 15146,8770 15149,9140 15152,6336 15155,8096 15160,9498 15164,8453 15165,4651 15166,9012 15170,7775 15172,5033 15175,6350 15178,7455 15179,7651 15182,5680 15185,7865 15190,4552 15191,5729 15193,10478 15196,9775 15197,9605 15199,6798 15201,7469 15206,7399 15211,5876 15215,7330 15220,6080 15224,10152 15228,8191 15229,8259 15234,8975 15237,4929 15240,10137 15243,6171 15245,5734 15250,5885 15251,9320 15254,10360 15257,8757 15259,7183 15262,7899 15264,5345 15268,10090 15270,5230 15274,6264 15275,9398 15276,7083 15279,8208 15281,6488 15284,7221 15287,6691 15291,5503 15296,6418 15299,5367 15300,4574 15302,5406 15307,8783 15312,5485 15315,9601 15320,4853 15324,6665 15325,4830 15328,4717 15331,7769 15334,10251 15335,8871 15340,4939 15343,5009 15347,10129 15349,6862 15351,7125 15356,6933 15358,10341 15360,5481 15362,7258 15366,9391 15368,6716 15371,5540 15376,6938 15379,7698 15384,9326 15386,5441 15389,8249 15390,7692 15394,4959 15395,6025 15396,10429 15399,8164 15400,5249 15403,6140 15406,7430 15411,6985 15414,7550 15417,8687 15422,10358 15424,5047 15428,4569 15429,7602 15434,7173 15437,5781 15438,6256 15443,9254 15444,7067 15449,5572 15452,8578 15457,5658 15462,9458 15467,9404 15471,9560 15476,8469 15479,8687 15484,9023 15485,4769 15486,9987 15489,9830 15492,7081 15493,4446 15494,5970 15495,4910 15497,9114 15502,7634 15505,5011 15506,8273 15508,10137 15509,7899 15510,8270 15513,7337 15515,4892 15519,6997 15520,4456 15521,4702 15524,6492 15528,7585 15532,7279 15535,5675 15538,10178 15539,7680 15542,8915 15546,8606 15547,5540 15548,6045 15553,4979 15555,10247 15557,10074 15558,4496 15560,8836 15564,5252 15567,6328 15569,5077 15571,8347 15574,9823 15575,5457 15576,6275 15579,8990 15584,8602 15587,7020 15589,7650 15590,8934 15594,7655 15598,9536 15601,7014 15605,5862 15607,9756 15610,7063 15612,8028 15617,10277 15621,7102 15625,8689 15626,4854 15631,6849 15636,9080 15640,9384 15645,4605 15649,5168 15653,9076 15658,10487 15660,9701 15664,8014 15669,4683 15671,5274 15676,7757 15680,8500 15682,5450 15684,7255 15688,5045 15691,4550 15693,7841 15698,5489 15699,4416 15701,5205 15702,7164 15706,8306 15711,7207 15713,7891 15714,5251 15716,8930 15719,8553 15720,6171 15722,9748 15727,4823 15728,5580 15732,8089 15734,6867 15738,8339 15739,6222 15743,4719 15748,10031 15753,9231 15757,9910 15759,5806 15763,4518 15765,6284 15769,7699 15774,4697 15775,9820 15776,8273 15780,7287 15784,6747 15789,7539 15790,7547 15795,4946 15798,4396 15801,5515 15805,9896 15806,7144 15809,5495 15811,4547 15816,8798 15818,8202 15820,10226 15821,5596 15823,6469 15826,5199 15829,4871 15834,9502 15839,10474 15844,4913 15847,4998 15851,4708 15852,5148 15857,8245 15859,6484 15860,6433 15865,6384 15867,8460 15868,9792 15870,9410 15873,6558 15877,8486 15882,5170 15885,7358 15890,6934 15892,8686 15895,7773 15898,9685 15900,4858 15904,9688 15905,4411 15907,9295 15909,6894 15910,4855 15913,7088 15917,6112 15920,8195 15921,7554 15924,10399 15926,7265 15930,9218 15933,10458 15936,5718 15939,10487 15940,5650 15945,5549 15947,8426 15950,10349 15954,4401 15959,8887 15962,10112 15965,8347 15969,8476 15970,9292 15972,5812 15974,9610 15977,7742 15978,4782 15981,6146 15982,8899 15987,8210 15990,9894 15995,4516 15998,8401 16002,9047 16006,8356 16011,7319 16012,6107 16017,5296 16022,4994 16027,9796 16032,5518 16037,8892 16038,8372 16039,5692 16040,8177 16045,8621 16048,8815 16050,10376 16053,5014 16055,10066 16059,10457 16060,6238 16065,8369 16066,7361 16070,6390 16073,8667 16076,4681 16079,5058 16084,8963 16088,9869 16089,8911 16093,6932 16098,7280 16102,9218 16104,6558 16108,6252 16110,6578 16112,5826 16117,5735 16120,4547 16121,10431 16125,10095 16130,6525 16135,6860 16138,7890 16142,7753 16145,6205 16147,8930 16152,6501 16154,8545 16155,7478 16156,4555 16159,8384 16160,7896 16161,6268 16162,10104 16165,6967 16169,9776 16173,9648 16178,9703 16181,8641 16185,10349 16190,8069 16191,9362 16196,7869 16199,9500 16203,4386 16208,5161 16209,8599 16211,4790 16215,9786 16220,5757 16222,8625 16227,4612 16231,5859 16232,4619 16236,8578 16237,6019 16242,8942 16246,9112 16248,9034 16252,7273 16257,5805 16262,4864 16263,9070 16268,5427 16270,7659 16271,5845 16276,7247 16279,7435 16280,6570 16285,10061 16286,7465 16291,7423 16292,6238 16297,9962 16298,9372 16300,7509 16304,4576 16308,4443 16310,8857 16314,5958 16315,7293 16320,6355 16323,6996 16327,6427 16329,9543 16331,8145 16335,6308 16340,5915 16341,10122 16342,5720 16345,9638 16349,5139 16351,8299 16355,7529 16359,4427 16360,9241 16362,6377 16363,6127 16365,9396 16370,7934 16375,4680 16379,8608 16380,8408 16383,5311 16384,7393 16386,5471 16389,9263 16393,8981 16398,5632 16399,6526 16401,5072 16405,10446 16406,10091 16410,8739 16414,8868 16417,9113 16419,5275 16422,8505 16424,9861 16425,6273 16427,6652 16432,4921 16433,8287 16435,9285 16438,4883 16443,6822 16448,5477 16449,4586 16452,7467 16455,8278 16460,7751 16465,5721 16466,10328 16469,5321 16470,6032 16471,6028 16474,9567 16479,7619 16484,6172 16485,6296 16489,4390 16492,7668 16496,7938 16498,5766 16502,9589 16505,5903 16508,5543 16510,6909 16514,6261 16516,10147 16517,7992 16522,5676 16526,10467 16529,8435 16534,9876 16537,9017 16539,8726 16544,9779 16546,6023 16551,4532 16553,7616 16557,6823 16561,6803 16565,5700 16568,5718 16570,6078 16575,8447 16577,9961 16580,4380 16584,8784 16588,9231 16593,5833 16596,4913 16601,9411 16605,7511 16610,9997 16613,7276 16616,7539 16618,6950 16622,6027 16626,9854 16629,6691 16633,4879 16635,8060 16636,9837 16637,7513 16639,10032 16642,6210 16644,9431 16645,8309 16650,10093 16651,9110 16652,7832 16655,10435 16659,4963 16661,9754 16663,7443 16666,9508 16670,8096 16674,7459 16679,7499 16683,7602 16686,6933 16687,8512 16689,5842 16694,9243 16697,7439 16698,9387 16703,6888 16706,10147 16707,5852 16709,4695 16711,4517 16714,8612 16717,7159 16718,5710 16719,5528 16723,5582 16725,5686 16729,7209 16734,5637 16737,5176 16741,6648 16746,8121 16748,5429 16749,6519 16754,6743 16758,4656 16760,6076 16765,8388 16768,4455 16773,6081 16778,5684 16779,10025 16780,7040 16783,7867 16787,9595 16792,10080 16794,6705 16797,6264 16801,7381 16803,9198 16805,8576 16806,7594 16809,5323 16814,5422 16818,4753 16823,5236 16828,4841 16831,5228 16836,9919 16839,8908 16844,7278 16848,8631 16852,9078 16855,10041 16857,5937 16859,5209 16863,5235 16864,6793 16867,5732 16868,10132 16870,4662 16871,9355 16876,6240 16880,9410 16881,10358 16885,10330 16889,5368 16890,9821 16892,5041 16897,6216 16900,5880 16903,4979 16907,9971 16910,10172 16911,4657 16915,8763 16919,10117 16921,7781 16924,7855 16927,10365 16932,6613 16936,6177 16940,6921 16941,5895 16945,9253 16950,4598 16955,7186 16957,8558 16958,5153 16959,6061 16964,10254 16966,6598 16968,7658 16971,7780 16972,4439 16973,4953 16976,5631 16981,9865 16983,8577 16986,9383 16988,5179 16989,8459 16992,7700 16995,7896 16996,8975 17001,8440 17003,6166 17004,5256 17005,7541 17007,4562 17012,8488 17015,8839 17019,9767 17024,9607 17028,7216 17029,9581 17034,6709 17037,8182 17039,9482 17040,7660 17041,8352 17046,7349 17048,8419 17051,8709 17052,9223 17057,7021 17059,9559 17063,9079 17065,7472 17068,7549 17070,8879 17075,5799 17080,6229 17084,5396 17088,7035 17091,8066 17095,6671 17099,4591 17102,10012 17105,8327 17106,9059 17111,9453 17115,9508 17116,4470 17117,4383 17120,8074 17124,6297 17128,9592 17129,9494 17132,9754 17135,9233 17138,10064 17142,8657 17146,9276 17147,5045 17148,9857 17152,10158 17157,7225 17161,8653 17163,5747 17168,9864 17170,5422 17172,9364 17175,8343 17178,7500 17183,5497 17186,6746 17191,8842 17193,8641 17196,6307 17201,5761 17203,10444 17206,9332 17208,10485 17211,5648 17213,8159 17214,6745 17219,8543 17223,4701 17227,5675 17230,9739 17235,6650 17240,7124 17244,7037 17247,4809 17251,10407 17253,10217 17257,4626 17258,9438 17260,10071 17264,9410 17268,5499 17273,10068 17277,7940 17280,6670 17283,8582 17284,4920 17287,5785 17288,5882 17291,5797 17295,10284 17296,5967 17301,8573 17302,4429 17307,7555 17308,5171 17312,8914 17314,6259 17315,5114 17317,7927 17322,5382 17326,9593 17327,5169 17330,4499 17335,9321 17340,9965 17343,6095 17345,6976 17348,6952 17353,7717 17358,9495 17360,9290 17364,9504 17368,4551 17369,9760 17370,9698 17372,4533 17376,8696 17379,7568 17383,8493 17384,7196 17385,8340 17388,6882 17389,6111 17390,6894 17391,6728 17392,6354 17396,6177 17400,7511 17405,7304 17406,4532 17410,8977 17415,7846 17417,7055 17421,5575 17426,6012 17428,7086 17431,6968 17434,6139 17439,8524 17444,8281 17448,6832 17449,4864 17452,6400 17455,9113 17458,7862 17462,8300 17465,8208 17467,9101 17471,5527 17472,5023 17474,7017 17477,8198 17478,4655 17482,9101 17484,7731 17487,7525 17491,10362 17496,6150 17499,7381 17502,6155 17506,6761 17509,8321 17510,4409 17511,10154 17515,9965 17518,10068 17521,7453 17524,4795 17525,10475 17528,10080 17529,4884 17530,6157 17534,5912 17535,8932 17540,10397 17542,10158 17547,5529 17552,6568 17557,8074 17558,4406 17560,6157 17565,8232 17568,4910 17572,7450 17574,4696 17575,5544 17577,9681 17580,9629 17581,9145 17586,10242 17590,8786 17595,6701 17597,7163 17602,5127 17604,9999 17606,8050 17610,8401 17613,9445 17616,5479 17618,8065 17621,8490 17623,9579 17625,10440 17627,5745 17628,10348 17631,7785 17634,9067 17637,8893 17640,8299 17642,4857 17647,9410 17650,7793 17652,5205 17656,4397 17661,10024 17666,8439 17668,8615 17671,8084 17675,8922 17677,9728 17678,8914 17682,5165 17686,4655 17691,10431 17692,4744 17697,7637 17700,6148 17702,5682 17707,9641 17708,7979 17713,5318 17715,8189 17718,7126 17719,6171 17724,9335 17728,10024 17729,6221 17734,4641 17736,5167 17740,5754 17745,5689 17749,9875 17753,6069 17756,6610 17759,4497 17764,7468 17767,5887 17772,7483 17777,8626 17778,5805 17781,4719 17785,7108 17786,9836 17790,8779 17791,9182 17796,8744 17797,8202 17801,7108 17803,9258 17808,9157 17810,5762 17814,5593 17815,8234 17820,5993 17825,8662 17828,10473 17831,6763 17832,5380 17833,8474 17834,7249 17836,7585 17837,8933 17838,8807 17840,8069 17844,9947 17849,6102 17854,5541 17859,5299 17864,8337 17866,9336 17868,9442 17872,9968 17874,7752 17877,8443 17882,9599 17883,9026 17885,10333 17889,6769 17892,5713 17895,8703 17898,9229 17899,4441 17903,8935 17907,7488 17908,10484 17910,7051 17915,8205 17916,5416 17919,8382 17922,9106 17924,5007 17929,6046 17931,6597 17935,4695 17938,10309 17939,5357 17943,6677 17947,6006 17950,5178 17954,6767 17959,7761 17963,6024 17966,5145 17970,7232 17974,7172 17979,4774 17980,7945 17985,9091 17987,4617 17989,9481 17991,9101 17992,4994 17996,8306 17997,8402 18001,6882 18003,4716 18008,9288 18011,4946 18012,4744 18017,7657 18022,8886 18024,7924 18027,7922 18032,9604 18033,8382 18036,6841 18037,6292 18038,8013 18043,5951 18046,9922 18048,7798 18053,4552 18056,5979 18057,8298 18060,6992 18065,9887 18068,7667 18071,9119 18074,7231 18075,9443 18076,7197 18080,10227 18082,4406 18084,5089 18088,7993 18090,5741 18092,5239 18095,9905 18097,5037 18099,8258 18104,4775 18106,7532 18108,8982 18110,4755 18115,6529 18120,7230 18125,8580 18127,5121 18129,8144 18132,9408 18137,9107 18141,5934 18145,7875 18147,10264 18152,8943 18156,4529 18158,8046 18159,8586 18160,8896 18163,9763 18168,4570 18172,6302 18174,4863 18177,7172 18181,8895 18182,8568 18186,6505 18190,5135 18193,6498 18198,8192 18199,4467 18203,6886 18207,6545 18210,10185 18213,5174 18214,9543 18215,9159 18220,5036 18224,6177 18229,9457 18232,10167 18234,5700 18235,9124 18237,4605 18241,6311 18243,5709 18246,9004 18251,8857 18255,5666 18259,10281 18263,6804 18268,9164 18269,4677 18274,4958 18279,7030 18281,4392 18284,10391 18286,7238 18289,4687 18292,9700 18297,5360 18299,9968 18301,10356 18304,4954 18306,9100 18308,7758 18310,10235 18312,6906 18313,6318 18315,9932 18319,8452 18321,9297 18324,9786 18325,9138 18328,4511 18331,6967 18334,7702 18335,8628 18340,8154 18342,7738 18343,8579 18344,4609 18345,6114 18349,4654 18350,4677 18351,9735 18354,4919 18357,6781 18360,6865 18364,9576 18367,8781 18368,5088 18371,5203 18376,10164 18378,4824 18382,9768 18385,7048 18386,5980 18388,7507 18390,7950 18393,5267 18396,6674 18400,9384 18403,6775 18405,9458 18407,4691 18412,5029 18414,9620 18419,9217 18424,7600 18426,5504 18429,9592 18431,9830 18434,9780 18438,8824 18442,9198 18445,5019 18447,6105 18449,5546 18454,7935 18456,7008 18458,9540 18459,4849 18462,10268 18466,7136 18471,6345 18472,5924 18475,10274 18480,6970 18483,6321 18487,6488 18488,4707 18489,7086 18494,6170 18495,9460 18499,8594 18504,6492 18509,9727 18513,5311 18517,7202 18520,5564 18524,6927 18526,9621 18531,8539 18535,7268 18540,8443 18541,8331 18542,4502 18547,8592 18548,5488 18552,8090 18557,9707 18561,7421 18563,8665 18568,5921 18573,6878 18577,5961 18581,10185 18582,8264 18584,8962 18586,5420 18588,9667 18591,5804 18596,5774 18600,8418 18604,9505 18608,5253 18609,8960 18611,7604 18612,9043 18616,8903 18621,5843 18626,5308 18627,10341 18628,6081 18629,8252 18632,8707 18636,9676 18640,6751 18644,7282 18647,5445 18652,4919 18653,6080 18656,10448 18658,4505 18660,5632 18664,10149 18669,9551 18671,9117 18675,4599 18678,10226 18682,8019 18686,6135 18688,5591 18692,7085 18694,5674 18698,5135 18703,6547 18707,5886 18709,4965 18714,4673 18715,8563 18716,7714 18721,8801 18722,6105 18727,4836 18732,10257 18734,7918 18735,9557 18738,9458 18741,9368 18746,7762 18750,8838 18752,4811 18756,6648 18759,5906 18762,5379 18765,5146 18770,6542 18772,9073 18776,8214 18780,5074 18783,8697 18786,7987 18789,10057 18791,7809 18794,8429 18797,9095 18798,6568 18803,6238 18807,7749 18812,9776 18815,4909 18820,9464 18821,6559 18824,7432 18828,4964 18829,8623 18831,5572 18835,4953 18837,4958 18839,6271 18840,8469 18842,4556 18844,8407 18848,10088 18851,8973 18854,6478 18859,7686 18864,10084 18867,5369 18868,5450 18872,5694 18877,8166 18878,7099 18883,8957 18885,7881 18888,9238 18889,8825 18893,8193 18898,5606 18899,7836 18901,10132 18905,8450 18907,8551 18910,7282 18914,7281 18916,8588 18918,9702 18923,8519 18928,5643 18933,4808 18935,5402 18938,5212 18939,9262 18942,8912 18947,8812 18950,6392 18954,9992 18957,5781 18960,7381 18964,7616 18969,9101 18973,6307 18978,9495 18981,9075 18982,5567 18983,9810 18985,9155 18989,6881 18994,8448 18996,9838 19001,8666 19006,5923 19008,4722 19013,9809 19017,6237 19018,7723 19019,4954 19022,6804 19023,7406 19027,4659 19029,4807 19034,6765 19036,8915 19041,7694 19046,8589 19050,7733 19051,7971 19055,6578 19060,10305 19065,5449 19068,9072 19072,6358 19075,7627 19077,4713 19082,9520 19086,9703 19088,8160 19090,7402 19092,10049 19095,8084 19097,5777 19100,4465 19103,9789 19108,10037 19111,5660 19115,5471 19116,9489 19121,8682 19122,9748 19123,4815 19127,7922 19128,8174 19131,8104 19134,8899 19137,8612 19138,6022 19142,6348 19147,5198 19151,6801 19154,8225 19156,5268 19161,8824 19163,8493 19164,6304 19165,9163 19169,4426 19171,6664 19176,7170 19177,9786 19179,7895 19183,10194 19185,4534 19188,6198 19193,9150 19195,6225 19199,9410 19202,5481 19205,5037 19210,5896 19215,5356 19220,6107 19221,6406 19224,7108 19225,8843 19229,4463 19230,7739 19234,9774 19236,6782 19237,8324 19238,9611 19243,8531 19248,5757 19250,8705 19253,5203 19254,9126 19255,5589 19256,6774 19257,6294 19262,9018 19267,5631 19272,5661 19276,6942 19279,9596 19284,7402 19285,5544 19290,6576 19294,7832 19298,6730 19301,6758 19303,8921 19306,7252 19310,5983 19312,6488 19317,4993 19319,5569 19322,5270 19324,8723 19329,9852 19331,8338 19332,7333 19333,5498 19338,5244 19342,6299 19343,4624 19346,5595 19349,4752 19350,6074 19351,9163 19356,4570 19360,8610 19365,4428 19366,5325 19369,7999 19370,7847 19372,10193 19374,4565 19376,5895 19377,5321 19379,6999 19380,7541 19385,6287 19390,6800 19394,8830 19395,8088 19397,6693 19398,6451 19401,7802 19403,6830 19408,8544 19412,9435 19414,7947 19419,7817 19420,4944 19425,6593 19430,5192 19432,9691 19435,10463 19439,10467 19442,7705 19445,6536 19448,9020 19451,5529 19452,6350 19455,5733 19460,9507 19461,8140 19465,6526 19468,8941 19472,10230 19475,7460 19478,9412 19479,7374 19481,9967 19484,9563 19489,8212 19492,6833 19497,9453 19501,6841 19502,5802 19505,7510 19508,9385 19513,5912 19518,5723 19522,9696 19525,7418 19529,4794 19534,9289 19538,9839 19540,8608 19542,5146 19544,8623 19549,9043 19551,9566 19553,5513 19555,8204 19558,5214 19560,9682 19561,7764 19564,8637 19566,4437 19569,4403 19574,6094 19579,7001 19582,7615 19587,8699 19591,6247 19596,10323 19598,8643 19601,10130 19606,6925 19610,5568 19614,5829 19618,10117 19621,5497 19626,6072 19627,7716 19630,5496 19631,8040 19634,6590 19638,4541 19642,5454 19644,8631 19645,8465 19647,8715 19649,7732 19651,4412 19654,7012 19655,6823 19657,8552 19658,8146 19663,8815 19665,4966 19668,7326 19670,7830 19671,4475 19672,7912 19675,8245 19680,5681 19684,7223 19685,8719 19687,5156 19690,7900 19693,10297 19694,8863 19698,4822 19699,10000 19701,9834 19704,7263 19707,5850 19710,6917 19711,7882 19714,6527 19715,8828 19719,9533 19721,4767 19722,6690 19725,4546 19729,6406 19731,9335 19735,5555 19740,6322 19743,9271 19745,6277 19750,9401 19754,6073 19757,8274 19759,5014 19762,5787 19765,5567 19766,7894 19767,7260 19769,7945 19772,10021 19775,6981 19776,4684 19778,8872 19782,5030 19787,4727 19788,6336 19793,6129 19795,8321 19798,4813 19803,7890 19807,4485 19809,4742 19811,5874 19815,7342 19816,9542 19821,4490 19823,4468 19828,8683 19829,9177 19834,8645 19837,5002 19838,4768 19843,5433 19847,5120 19852,9580 19857,9359 19861,8709 19865,7320 19870,4680 19873,4593 19874,7705 19876,5092 19880,6534 19881,8679 19882,7260 19885,4913 19886,5864 19889,9439 19894,9728 19898,6579 19903,7059 19904,5847 19905,5174 19910,4956 19915,10249 19920,7707 19921,10237 19926,9861 19929,10125 19931,9420 19936,8628 19938,6846 19943,5477 19947,7417 19949,8743 19952,9288 19955,5085 19957,5331 19961,8267 19963,6973 19968,8559 19971,6574 19973,6194 19974,7620 19976,5222 19977,10338 19979,7108 19980,9287 19981,4731 19986,10088 19989,6138 19990,8744 19994,9111 19999,4400 20002,7248 20003,9240 20005,7185 20008,8415 20011,4694 20012,6974 20015,8190 20020,5366 20024,7100 20029,6158 20032,9789 20035,4971 20037,7016 20042,10113 20044,4831 20048,7927 20053,10393 20054,6771 20056,9458 20059,5149 20061,8648 20065,7166 20070,9175 20072,8008 20076,7061 20077,9747 20079,8946 20080,8983 20084,10274 20088,6110 20089,5716 20094,6130 20095,9672 20100,5287 20101,6515 20103,10457 20104,9786 20107,9606 20109,6840 20114,6750 20119,6648 20120,5585 20123,8889 20127,8488 20129,6761 20134,9001 20139,5290 20140,5649 20145,8626 20150,6728 20151,6876 20152,9275 20154,4484 20155,9400 20158,5754 20159,5818 20162,8266 20163,7097 20168,9274 20172,7877 20177,7561 20180,7565 20184,5798 20185,6532 20186,8550 20188,7702 20190,4762 20194,5503 20196,7766 20198,5290 20203,8182 20204,7897 20208,5544 20211,6213 20212,6314 20217,5706 20220,9326 20224,4988 20225,5339 20226,5423 20230,5798 20235,4694 20236,5401 20237,6514 20240,9602 20243,9662 20246,7839 20247,7213 20249,6155 20250,7363 20253,6574 20255,7988 20258,6032 20262,10008 20266,8998 20271,8402 20272,4844 20275,8929 20276,6642 20277,8128 20280,5215 20282,4381 20285,8321 20286,8328 20290,8944 20294,4648 20297,5145 20298,7096 20301,8718 20302,8071 20303,7598 20306,8230 20307,9459 20311,6246 20315,10337 20320,6592 20324,8429 20326,9092 20328,6436 20331,5579 20334,6373 20339,6159 20343,9540 20347,4406 20348,9914 20351,5286 20355,4589 20356,6104 20358,4489 20362,9254 20367,8294 20368,5257 20369,5393 20370,9039 20373,9697 20377,5895 20379,10083 20381,8197 20383,6794 20387,4978 20389,6864 20391,9641 20393,6393 20395,10444 20398,7743 20402,6573 20406,8012 20408,9884 20413,8919 20415,5155 20419,7043 20420,10289 20425,9904 20427,5274 20431,7826 20433,9672 20438,9182 20439,6464 20444,8035 20447,7987 20448,10068 20449,5624 20450,7910 20454,8158 20457,6292 20461,9875 20466,8026 20469,5707 20471,8511 20474,7416 20478,6101 20481,9036 20484,4575 20489,5729 20492,8444 20496,5580 20499,6788 20501,8148 20505,9327 20510,8344 20511,4883 20516,8832 20520,9935 20523,10123 20526,6771 20529,6167 20533,9360 20535,5389 20540,6407 20545,7537 20550,6799 20552,6117 20556,10015 20558,7014 20559,6397 20561,6249 20566,5948 20569,5539 20574,5336 20579,4716 20581,9606 20583,8281 20585,10362 20590,5785 20591,7786 20593,8968 20597,7723 20600,10212 20603,7088 20608,7422 20613,6770 20617,7678 20622,9293 20627,6085 20630,9845 20632,8493 20633,10160 20635,5389 20639,6364 20641,8796 20646,8252 20649,9926 20650,9245 20653,6226 20654,8736 20656,7164 20657,6393 20662,9506 20667,10288 20669,7477 20674,7948 20676,8608 20680,9200 20685,4478 20688,7815 20689,5250 20691,8007 20695,6887 20697,6446 20700,8534 20701,7416 20706,8365 20711,9240 20713,7244 20714,4499 20716,8342 20717,7354 20718,7208 20723,4924 20727,5374 20731,7166 20733,8734 20735,4842 20738,5040 20741,9681 20744,7083 20745,9861 20749,7693 20754,10454 20757,6856 20762,9077 20763,5104 20766,9132 20768,6669 20772,10380 20776,4651 20781,10257 20784,6880 20789,7170 20794,6709 20797,10480 20799,6122 20803,4480 20808,6378 20812,9093 20813,7053 20816,9534 20820,7069 20821,8588 20825,5513 20826,5894 20828,6540 20832,6275 20833,5459 20837,6172 20841,6719 20844,7715 20846,9538 20850,5335 20854,9643 20858,8586 20861,7913 20863,5802 20864,6636 20867,6049 20869,7935 20874,8416 20877,6132 20879,9907 20884,10284 20889,4751 20892,8506 20896,7124 20899,5340 20903,5797 20906,7022 20907,8753 20911,6803 20915,5395 20917,6714 20918,6258 20919,8792 20923,10275 20924,7953 20927,8653 20929,7695 20931,8046 20935,7155 20940,6693 20943,8708 20944,7212 20945,9530 20947,6781 20951,10235 20953,8189 20957,5590 20959,8926 20961,6671 20962,7888 20966,6360 20969,9414 20974,9976 20977,6764 20978,8992 20979,8656 20984,7001 20987,7210 20988,9709 20992,5410 20993,4876 20998,9014 21003,9282 21004,5076 21009,5138 21013,6381 21015,6900 21020,9130 21024,5209 21029,6998 21030,8057 21031,7735 21035,5095 21040,8819 21042,4780 21043,9583 21044,8181 21047,10075 21049,4984 21053,7200 21058,4946 21063,7313 21064,9208 21065,7361 21067,8763 21072,9342 21077,8068 21081,6975 21085,9637 21086,7240 21090,7237 21095,8346 21097,5151 21102,9646 21104,8111 21105,4655 21109,8446 21110,4454 21111,10430 21114,5676 21115,5606 21120,5714 21124,8251 21128,8389 21132,5921 21137,5372 21140,7228 21144,5445 21145,6822 21149,5979 21151,9221 21153,9657 21154,7923 21159,5418 21162,7481 21164,5446 21167,8589 21168,9830 21172,5133 21174,9409 21179,6254 21181,9447 21184,5678 21185,10039 21187,4589 21192,4693 21195,7726 21200,6865 21203,6315 21205,6808 21208,5296 21211,9104 21215,8881 21220,5937 21225,4384 21230,5484 21235,4551 21236,7915 21241,6706 21245,10069 21249,9525 21253,5299 21257,7546 21262,6696 21263,10356 21264,5324 21269,4708 21271,7514 21275,6380 21276,8882 21277,6668 21281,4702 21282,6833 21286,6887 21288,6150 21290,8159 21291,5407 21294,5283 21295,9755 21298,7655 21299,6326 21301,8416 21303,5910 21304,8261 21306,7702 21308,5460 21310,6047 21312,10185 21315,9177 21319,4875 21321,9935 21322,5552 21326,5548 21329,6319 21331,5015 21332,4795 21333,7785 21338,5328 21342,9880 21345,6187 21346,4595 21351,6825 21355,7413 21356,5908 21357,4490 21360,9547 21365,6353 21366,4847 21368,5837 21371,4430 21376,4702 21378,5335 21383,4521 21388,8019 21392,6046 21394,4780 21399,5002 21404,6814 21405,5842 21409,6023 21410,8339 21411,8799 21413,9265 21417,6964 21422,9661 21423,6912 21425,5966 21430,5333 21432,5190 21436,10326 21441,7585 21443,8907 21447,7902 21450,10355 21455,5056 21460,10353 21463,8251 21464,10025 21465,7885 21470,9978 21475,5914 21477,6993 21480,7101 21485,4924 21487,6843 21492,6781 21495,6980 21500,7727 21504,8758 21508,10259 21513,7645 21514,5915 21517,7440 21518,5523 21523,5516 21524,6093 21529,7968 21532,6826 21533,7375 21536,7890 21541,6691 21544,7028 21546,7365 21548,6862 21553,7043 21557,4967 21560,6723 21561,5805 21563,6533 21567,5048 21568,9311 21573,8013 21574,8205 21579,8643 21580,9392 21584,8738 21585,5356 21590,7439 21595,5756 21598,5868 21603,8004 21604,6575 21607,7935 21608,10475 21610,4729 21613,4905 21614,10456 21617,5017 21622,5220 21627,6801 21628,7277 21630,8270 21632,8239 21633,7559 21634,7996 21636,10416 21638,7029 21641,5248 21644,8989 21645,9537 21647,9291 21651,9039 21655,9629 21660,6727 21663,7623 21664,5494 21668,6142 21670,6726 21675,10064 21679,7474 21681,7020 21685,6740 21688,9247 21689,4445 21692,4895 21694,4982 21696,7617 21697,7619 21699,6480 21701,6053 21705,5970 21706,8116 21707,7462 21712,6316 21713,4621 21716,6491 21720,8773 21724,6957 21727,7355 21731,5054 21736,10329 21740,5750 21745,9827 21749,6161 21750,4736 21755,9470 21757,6703 21759,9366 21761,6312 21763,8463 21767,4915 21768,6366 21772,5136 21777,7826 21782,5267 21787,4810 21789,6535 21790,9096 21793,6694 21798,9019 21803,8026 21806,6656 21808,5071 21813,5057 21816,7376 21820,6907 21824,8086 21829,9399 21834,8958 21836,5416 21837,9510 21840,9325 21843,9860 21848,4418 21853,5567 21854,4682 21858,8770 21862,9375 21867,4925 21872,6757 21876,7178 21880,6028 21883,4536 21886,4570 21889,9283 21890,10270 21891,8716 21894,10216 21899,9171 21902,7280 21905,8434 21906,4580 21909,5968 21910,4657 21912,10159 21913,4916 21915,8379 21920,6563 21922,10172 21927,5039 21931,5575 21932,4821 21933,7622 21936,6344 21938,9635 21943,7918 21944,6521 21949,5697 21952,4561 21955,9178 21957,10415 21962,8159 21963,6071 21968,4714 21972,7906 21977,7653 21979,10401 21983,5573 21987,9755 21990,10257 21992,7096 21997,6209 22002,8748 22004,5436 22008,9423 22009,7615 22014,10177 22016,6940 22019,10488 22021,4589 22022,4537 22024,5240 22029,6355 22034,7977 22037,5342 22040,9849 22041,10051 22044,8781 22046,7199 22050,10341 22052,7306 22057,6390 22058,7163 22062,9504 22067,8757 22072,6497 22075,6167 22076,5902 22080,7600 22085,10346 22089,8170 22091,9246 22092,9871 22093,9272 22098,7403 22099,9020 22102,7361 22106,7803 22109,8161 22110,6641 22114,8490 22116,8988 22119,9673 22120,7569 22124,5044 22126,8491 22127,8386 22131,8978 22132,9448 22134,6742 22138,7705 22141,7508 22145,9020 22150,7617 22155,9811 22156,9190 22158,6054 22162,7843 22166,9311 22167,5849 22171,7963 22173,7331 22178,8022 22182,6110 22186,9327 22188,9253 22191,6554 22193,7344 22198,7133 22200,9834 22202,5184 22206,5365 22210,4952 22212,6534 22217,5619 22219,6083 22221,5880 22223,5787 22224,4465 22227,8891 22229,8641 22232,7137 22235,9475 22237,9556 22241,8438 22243,6959 22244,8682 22245,8058 22250,7757 22251,10451 22252,8777 22255,8588 22259,5980 22264,9642 22268,5404 22272,9581 22274,10386 22279,9375 22284,6474 22288,5945 22291,6873 22294,7423 22298,5893 22301,6811 22304,4544 22307,6798 22310,8505 22313,10444 22315,8012 22317,10321 22318,10326 22323,8875 22327,6214 22329,10447 22333,8561 22335,4702 22339,9112 22343,8019 22345,6734 22347,9807 22352,7343 22357,8792 22361,6630 22365,9242 22370,4569 22375,5746 22378,9518 22380,7356 22381,6773 22383,5767 22384,7651 22388,10290 22391,8673 22396,8041 22398,6748 22399,6547 22404,7452 22409,6529 22414,7584 22417,8437 22419,5254 22424,4582 22427,9175 22429,8634 22434,9815 22439,6696 22444,5450 22449,9094 22454,6154 22458,5351 22461,8181 22463,4847 22468,10315 22471,6261 22474,7164 22477,5878 22478,8600 22479,7095 22483,5047 22486,9082 22491,5158 22495,8789 22497,10400 22498,7202 22499,6508 22501,9868 22504,5977 22506,4699 22508,4803 22511,5159 22512,8588 22515,4986 22518,4994 22523,8643 22525,4548 22530,10276 22534,10415 22535,7074 22536,4890 22538,9269 22541,5231 22544,10218 22547,8450 22552,5509 22554,8798 22556,9598 22559,6411 22560,10039 22561,7280 22566,7273 22570,4559 22571,10104 22573,5445 22578,4468 22583,7309 22588,6867 22593,6606 22595,8623 22597,6913 22602,8015 22603,6191 22608,9507 22613,9744 22617,7724 22618,9174 22619,10256 22624,4394 22628,4562 22631,6346 22635,7459 22640,4877 22644,4821 22648,4654 22651,6594 22654,5009 22655,4632 22658,8978 22662,8708 22663,5669 22667,9688 22671,5624 22672,8959 22674,10405 22677,6287 22682,7853 22683,8666 22685,7408 22687,8499 22692,7742 22693,8169 22694,8345 22699,5503 22700,5601 22701,9221 22704,6956 22709,9360 22711,9205 22716,9934 22721,4800 22722,7105 22727,7072 22730,8582 22735,6441 22737,6872 22739,9133 22743,8294 22748,6589 22750,8129 22753,4504 22756,9054 22761,5722 22765,8179 22767,6928 22768,10092 22769,5492 22772,5119 22776,7095 22781,8247 22786,8432 22788,5560 22790,6184 22791,6728 22793,4825 22795,9243 22796,6169 22801,8283 22804,6777 22805,7929 22806,5423 22807,4843 22809,9991 22810,9550 22815,4505 22817,10031 22821,5471 22823,9232 22825,7449 22827,8911 22829,10153 22834,9252 22839,8521 22840,4544 22844,4722 22849,5345 22851,6324 22852,5441 22853,7909 22857,6880 22858,6272 22863,8014 22866,8219 22870,7275 22875,10484 22878,7621 22880,5693 22882,6748 22887,8160 22889,7028 22893,9347 22896,10429 22897,6236 22901,9024 22906,6337 22911,4759 22913,7724 22918,7937 22920,8001 22922,4954 22925,4812 22929,9532 22930,8397 22934,6716 22939,9363 22942,5071 22944,6667 22947,8181 22948,5647 22949,4621 22954,6178 22959,9031 22961,10053 22966,8114 22967,9208 22968,9592 22973,4902 22976,6860 22980,9842 22985,4785 22988,4595 22989,6032 22990,10258 22994,6748 22996,6562 22998,9863 23003,9617 23004,7635 23009,9304 23014,6905 23018,7233 23020,6146 23022,4488 23025,9167 23026,4621 23027,10328 23028,10484 23030,9083 23032,8845 23035,5705 23038,4544 23040,8050 23044,7121 23048,6754 23050,7049 23055,9071 23057,5421 23062,10248 23064,7203 23066,5521 23071,5528 23073,9893 23077,6369 23079,10016 23080,10274 23081,7994 23084,9831 23085,7797 23088,9344 23091,8140 23096,8080 23099,5697 23101,4677 23106,8313 23111,6894 23112,7483 23117,10365 23119,9219 23124,5563 23129,7417 23131,7130 23135,7209 23140,9743 23141,5763 23143,8131 23146,8480 23150,8270 23152,6405 23155,9965 23156,9642 23157,4775 23158,4728 23163,5457 23167,9695 23170,4553 23173,9750 23176,9639 23178,8898 23182,8613 23184,6735 23185,7386 23190,6031 23193,7568 23196,6900 23201,6403 23204,9456 23209,9103 23214,5509 23215,7122 23217,5151 23221,8542 23226,4394 23230,10014 23234,5134 23235,8099 23238,5594 23239,5140 23244,5985 23249,8639 23251,8380 23256,5287 23261,8672 23262,8138 23266,7075 23270,5747 23273,9883 23274,6819 23277,6927 23279,10394 23284,8455 23287,10415 23292,9581 23297,5863 23299,9145 23302,7317 23307,7382 23310,5802 23315,7834 23318,5599 23319,4449 23322,6648 23323,5686 23324,4750 23325,8454 23330,6552 23335,5442 23338,9579 23343,10250 23344,4846 23347,8505 23351,8090 23355,6335 23359,8987 23361,4877 23363,6163 23366,5218 23368,5524 23370,7289 23371,9469 23372,7144 23373,6967 23377,4792 23379,5806 23381,5326 23386,10090 23389,5335 23394,8814 23395,8828 23400,5537 23405,6545 23408,8349 23411,6992 23413,8473 23417,7931 23421,5736 23426,7033 23428,7679 23431,8129 23434,7523 23437,7526 23439,5138 23444,5685 23449,9444 23450,4747 23452,10162 23457,7316 23462,8023 23466,5368 23469,4660 23473,10329 23478,8961 23480,8959 23484,9176 23489,7867 23491,6449 23495,10084 23497,7219 23501,7906 23504,4888 23507,7108 23509,5359 23514,5442 23517,7152 23519,5150 23524,10258 23526,10304 23529,8671 23530,7428 23532,9527 23535,6544 23536,6793 23539,9389 23540,7046 23545,6669 23548,4836 23550,9617 23554,6054 23555,5291 23556,6742 23559,9560 23561,8868 23566,10109 23570,4579 23571,8150 23573,4916 23574,7731 23577,4985 23582,5732 23586,8646 23588,4793 23592,4894 23594,9138 23597,4611 23598,4694 23601,5210 23602,7955 23606,4901 23608,8169 23611,10056 23614,8792 23615,4964 23616,10039 23621,8974 23622,4420 23625,5057 23628,8671 23631,6010 23635,10322 23637,8158 23638,8786 23641,6518 23645,7812 23648,6411 23649,7748 23653,5701 23655,6434 23659,5757 23660,5340 23665,10202 23668,9897 23670,5612 23675,6785 23680,6483 23683,6115 23685,9470 23688,4999 23690,5165 23692,9499 23696,4395 23697,8839 23698,5169 23703,5492 23708,6151 23711,4546 23716,8540 23720,6717 23723,7241 23728,6963 23731,7089 23732,8202 23737,7509 23740,6564 23744,6095 23748,5952 23751,4405 23753,9243 23754,8449 23755,8496 23759,4786 23763,10091 23766,9397 23770,7195 23771,10446 23773,5807 23775,5595 23778,8540 23779,7089 23783,7398 23785,5248 23786,7664 23789,5258 23790,6609 23793,10385 23797,5400 23798,6207 23802,5498 23805,9274 23809,10317 23814,8157 23815,8402 23819,7033 23820,5875 23821,6392 23825,6658 23829,7764 23834,5975 23836,8118 23838,8692 23841,10152 23846,9376 23848,9733 23850,9593 23855,8302 23856,4776 23860,7565 23865,10437 23870,6833 23871,9920 23872,4626 23877,5896 23882,10312 23883,10084 23885,6723 23890,4565 23893,5316 23895,9119 23899,5846 23904,4507 23905,8294 23909,5417 23911,8648 23916,8772 23917,6835 23918,9378 23923,7382 23927,5415 23928,5252 23930,8044 23935,10175 23938,7577 23942,6659 23945,10136 23947,7660 23949,8914 23952,4416 23957,8181 23959,8874 23960,4925 23964,7393 23965,5156 23967,5054 23972,10224 23975,5630 23978,9512 23982,6173 23983,5990 23985,7646 23988,5529 23989,9353 23994,5215 23997,8701 24002,5152 24005,5094 24006,8191 24011,5613 24013,5431 24015,9502 24017,7561 24018,4579 24023,4615 24027,9788 24028,5964 24033,6944 24037,8517 24040,6952 24042,4445 24045,7971 24050,5507 24051,9305 24056,7989 24058,9578 24060,5256 24061,10336 24066,5664 24071,4929 24074,8385 24077,9152 24081,4903 24085,6638 24088,6086 24089,9422 24090,7472 24093,10230 24094,5911 24098,5305 24100,6734 24105,7511 24110,8216 24111,7112 24113,9321 24118,5795 24120,8742 24122,5694 24124,4522 24125,6057 24130,8657 24134,9337 24139,9304 24141,5578 24142,5146 24143,5314 24147,8274 24149,5427 24154,9683 24156,5067 24159,9306 24163,8666 24164,9102 24165,9667 24169,8778 24171,6281 24175,7461 24176,9243 24181,8924 24182,7285 24186,8206 24189,7256 24191,6023 24195,5339 24196,5427 24199,7688 24204,7295 24209,7820 24210,4421 24215,4376 24216,8309 24219,9637 24222,5756 24226,6490 24227,4420 24230,8246 24235,5548 24240,8000 24243,5474 24244,8599 24248,5427 24249,6471 24251,8936 24254,5087 24258,10045 24260,8588 24263,9010 24267,8832 24271,6739 24276,8931 24281,5910 24286,7720 24289,8420 24293,7794 24298,4949 24299,5062 24303,7213 24306,9498 24309,9399 24310,9934 24312,6241 24314,6118 24315,6302 24316,9627 24320,8764 24323,9616 24327,7983 24329,4659 24334,9079 24335,5906 24336,5948 24341,5003 24344,8791 24345,8685 24346,7677 24349,6595 24352,6142 24357,4466 24360,5186 24365,9489 24367,10416 24369,4922 24372,4379 24373,8643 24378,10417 24382,7663 24384,8543 24386,5058 24388,8496 24392,7688 24396,8969 24399,4456 24400,6297 24403,5416 24404,6607 24405,8278 24409,5120 24410,9580 24414,5976 24417,4582 24420,6471 24423,10310 24427,8741 24429,7637 24430,9013 24434,6748 24437,5459 24442,7197 24447,10175 24450,8156 24452,4533 24453,6381 24457,10423 24459,5197 24462,5565 24466,6907 24468,6772 24473,7104 24475,5793 24476,5507 24478,6571 24481,5409 24483,8367 24484,9240 24486,7127 24491,9911 24492,6224 24497,7461 24500,7243 24504,6470 24505,6825 24508,7467 24509,9134 24514,8630 24517,8169 24519,6057 24522,10193 24527,6489 24530,4511 24531,9209 24534,8039 24537,7456 24541,4718 24546,6978 24550,8383 24551,9544 24552,7714 24555,9750 24558,10043 24559,7650 24561,7737 24562,10358 24565,6426 24569,7426 24571,5639 24575,9606 24578,7440 24580,8623 24584,9799 24587,5141 24590,7060 24595,9523 24598,5169 24601,10072 24602,4588 24605,10032 24608,4915 24610,6248 24613,5637 24614,6055 24617,5080 24620,5098 24625,10203 24627,8920 24629,10049 24630,6231 24632,4707 24633,7715 24637,8297 24640,4456 24641,8166 24642,8330 24646,9942 24649,6415 24654,10138 24655,7272 24658,4989 24663,6082 24665,5142 24668,4430 24672,8208 24677,6344 24679,5169 24683,6569 24685,5444 24688,7982 24693,5397 24695,9255 24700,10038 24702,8594 24705,8062 24708,10413 24710,8875 24714,5736 24717,9842 24720,4617 24725,4672 24730,6186 24735,10322 24736,10090 24740,10123 24741,9816 24745,9985 24746,10027 24750,9957 24755,9452 24759,5873 24764,5479 24765,5434 24770,7392 24774,10213 24778,10163 24780,9756 24785,6897 24789,5481 24792,5071 24797,10331 24802,6630 24804,9934 24809,9612 24812,10270 24813,9509 24817,8461 24818,7486 24822,9711 24826,10040 24829,5763 24830,7567 24832,6409 24836,8880 24838,9623 24841,9141 24844,4876 24847,8105 24848,8952 24853,7740 24857,7503 24861,5261 24865,9657 24870,7944 24875,10212 24879,4376 24882,7779 24884,8851 24886,4567 24889,6341 24893,10448 24898,8432 24903,5639 24908,9167 24910,6421 24911,8286 24913,6769 24915,4619 24917,7008 24921,4498 24926,8338 24930,9046 24933,8070 24936,5137 24937,5237 24942,5854 24946,8991 24949,6689 24950,4571 24951,7487 24955,4838 24957,5648 24958,8339 24962,8425 24963,8327 24968,5048 24971,9869 24975,8070 24980,5883 24982,10487 24984,6462 24989,7450 24992,5879 24996,7643 25000,9089 25003,7450 25008,8107 25011,7560 25012,9188 25017,6452 25018,6687 25019,8285 25020,10025 25023,7693 25028,5194 25029,10005 25034,6588 25035,7773 25036,5232 25038,6034 25039,10213 25043,6361 25047,7145 25049,7540 25052,5785 25055,6912 25059,4942 25061,8644 25064,5634 25069,6256 25071,8991 25074,7684 25078,10443 25082,10039 25085,4386 25089,9343 25091,6360 25095,5241 25099,6798 25100,8907 25104,6721 25105,5180 25109,4897 25114,7359 25119,10472 25121,4626 25126,8332 25131,8267 25135,10192 25136,4847 25139,5981 25142,5482 25146,5409 25149,9792 25153,9761 25155,9152 25160,7759 25163,9170 25168,6193 25169,8371 25174,9228 25175,10372 25177,4899 25180,6174 25181,10475 25186,5054 25191,7834 25193,6116 25195,10177 25200,7433 25204,8377 25209,9554 25214,7956 25215,7214 25216,9088 25220,6191 25221,5108 25223,6626 25225,4857 25229,9110 25234,7664 25236,10104 25238,5607 25241,5976 25242,4937 25246,9042 25251,7723 25256,6312 25257,5812 25258,9658 25261,4578 25266,9604 25268,9541 25269,4933 25273,6070 25278,7221 25279,9152 25282,9462 25286,8839 25289,4575 25293,10140 25298,9520 25300,9022 25305,6918 25309,6688 25310,10257 25311,7555 25312,7380 25317,8842 25319,6005 25324,5154 25328,5431 25333,7354 25334,8639 25335,6318 25340,4769 25344,6844 25347,5207 25351,8873 25353,7404 25355,8076 25356,9748 25359,8306 25360,9834 25363,8486 25364,7386 25369,8488 25373,6122 25376,6451 25379,7325 25384,10125 25389,5321 25390,9028 25394,5867 25397,8873 25402,5346 25404,7811 25405,8143 25406,10033 25410,6735 25415,9116 25419,6265 25420,7486 25421,8829 25426,5090 25431,10205 25435,6328 25439,6053 25442,6045 25447,5190 25450,5789 25453,10168 25454,6861 25459,8963 25462,6960 25463,8985 25467,7443 25468,7378 25473,8708 25478,4731 25481,10442 25486,9847 25490,8414 25492,8639 25497,5352 25498,5846 25499,7022 25501,7942 25505,9839 25506,7376 25507,4706 25510,5815 25513,7088 25515,4871 25516,9996 25519,10079 25520,5045 25524,9650 25525,7389 25528,8668 25529,10106 25534,8048 25536,8173 25540,9172 25541,5769 25546,7016 25547,7720 25552,8882 25553,6956 25558,7819 25563,7004 25566,4699 25569,7674 25572,5313 25576,10189 25579,10214 25580,4452 25583,8510 25587,6761 25588,10127 25593,9758 25596,8971 25600,6833 25601,7193 25602,5673 25606,6686 25608,5557 25613,10168 25615,10165 25617,10250 25622,5489 25623,7591 25625,7832 25630,10169 25632,5161 25634,5530 25637,5850 25641,7498 25642,9387 25645,8153 25646,6813 25650,9758 25653,6310 25658,9797 25660,7024 25665,4597 25666,6784 25668,7146 25669,9745 25674,8732 25676,10122 25681,7283 25685,7263 25688,10222 25689,6694 25691,6386 25692,8258 25694,7598 25698,7933 25702,10173 25703,10394 25704,10469 25709,9320 25710,5221 25712,4425 25714,7539 25716,6832 25720,7641 25722,4864 25726,4498 25729,5258 25732,5094 25736,6279 25739,5022 25743,5729 25744,8227 25746,7540 25749,8333 25754,6398 25755,7964 25758,4418 25759,8969 25760,9359 25762,8950 25763,7455 25765,9333 25768,8749 25769,8375 25770,8506 25771,6652 25774,7777 25775,10074 25779,4659 25780,6348 25783,7708 25788,8010 25789,9881 25791,9655 25796,10031 25801,10154 25802,9189 25805,6426 25810,5109 25814,9149 25818,6761 25821,5566 25824,8854 25826,9622 25830,7022 25831,7472 25835,10071 25839,8666 25844,5090 25849,5761 25854,6986 25859,6963 25860,9675 25864,4796 25865,7250 25867,8720 25868,9998 25869,10487 25871,5740 25873,7515 25876,7224 25880,7081 25882,6105 25887,8300 25892,6343 25893,6123 25896,8099 25899,7151 25903,8647 25908,5278 25912,9796 25917,8906 25921,5325 25923,4945 25928,5228 25933,5993 25934,6336 25935,6269 25940,8907 25942,5442 25944,4566 25945,4396 25948,5102 25953,6426 25957,5662 25962,8998 25964,9721 25965,4482 25967,7521 25972,5965 25973,5676 25978,9048 25981,5196 25982,6675 25985,10113 25986,5056 25991,8847 25993,8761 25997,5051 25998,5675 26000,4879 26004,8325 26009,8895 26013,7825 26016,7047 26018,5993 26019,9648 26024,4511 26028,8572 26033,7363 26037,8529 26042,5592 26044,4834 26045,5241 26046,7831 26049,4774 26050,8911 26052,7581 26054,7452 26056,5055 26060,7628 26065,4869 26070,7954 26073,5772 26076,5015 26078,8355 26081,9006 26082,6491 26085,7733 26087,6864 26090,8390 26094,10261 26095,6509 26098,9570 26099,9555 26103,4491 26106,6557 26108,5934 26111,7694 26113,7367 26115,9936 26119,6475 26121,6805 26123,8956 26124,7881 26128,6765 26129,7648 26131,6881 26132,6100 26135,7363 26140,8701 26145,9508 26146,8369 26151,7193 26154,8460 26156,5643 26157,8914 26162,4647 26165,5645 26168,7752 26170,7254 26171,5274 26176,7715 26180,5887 26185,6430 26189,6793 26191,7429 26192,6808 26195,8758 26196,5387 26197,10477 26199,7705 26200,8864 26205,8541 26210,8067 26211,7638 26216,7428 26220,4801 26225,7800 26229,9131 26230,4547 26231,4383 26236,6925 26239,7684 26241,5473 26242,8820 26246,9091 26250,6640 26253,7879 26255,8715 26259,7205 26263,4450 26264,5525 26269,10383 26274,9354 26278,7790 26280,5017 26284,9227 26287,6058 26289,9573 26292,7797 26297,10465 26298,5215 26300,9598 26305,5191 26308,5152 26312,9384 26317,8704 26322,9601 26323,7965 26324,6252 26326,6390 26327,5118 26332,8781 26333,8922 26336,6767 26337,7035 26338,8425 26343,4739 26348,5967 26352,8099 26357,4690 26358,6382 26360,5853 26364,5802 26365,7704 26366,10352 26371,4614 26373,7788 26378,4467 26379,7136 26382,5074 26385,8358 26390,6473 26392,8907 26397,9601 26400,5739 26404,4676 26408,5773 26412,7458 26414,7417 26415,8411 26420,7846 26421,7022 26426,5272 26430,9578 26435,7300 26440,4521 26441,6827 26444,7692 26447,9343 26448,8874 26450,5081 26454,9996 26455,8173 26458,9493 26461,6863 26466,6908 26471,4906 26473,8649 26477,5645 26481,8527 26486,4667 26491,6425 26495,6299 26499,9668 26502,7031 26506,8637 26510,8275 26514,8596 26515,9984 26519,5710 26522,5419 26527,9257 26530,6051 26534,10347 26538,5049 26541,10404 26543,7616 26544,4466 26547,5792 26552,10337 26554,4788 26557,5368 26558,10430 26563,9080 26565,9263 26567,6299 26571,8437 26576,5510 26579,9335 26581,8488 26585,9449 26590,5241 26595,8662 26597,5823 26601,7248 26602,8812 26605,4703 26608,7676 26611,9513 26612,6772 26616,6478 26618,5815 26619,4755 26622,8507 26627,8010 26630,6459 26635,10294 26640,6368 26645,7933 26650,6861 26652,8255 26656,4835 26661,9118 26664,10195 26668,5310 26670,10038 26672,6767 26673,8561 26676,6654 26677,8279 26680,5148 26683,7074 26688,8367 26691,5404 26695,7664 26700,7391 26701,7515 26705,6335 26708,9258 26710,9176 26714,5185 26717,6850 26720,9772 26724,8792 26727,7381 26732,7541 26736,5170 26739,4442 26742,8342 26745,7141 26748,5775 26749,7998 26753,6517 26756,5827 26758,8956 26761,8574 26765,9203 26766,6570 26767,10072 26770,10317 26771,4509 26772,9180 26776,6389 26780,8470 26783,8422 26788,8835 26790,8327 26793,9515 26798,5147 26803,7781 26808,7858 26809,6745 26814,6191 26819,7802 26822,7295 26825,5821 26826,6683 26831,9903 26834,5248 26838,6647 26839,6312 26841,10350 26844,8194 26846,9255 26847,5159 26850,5474 26852,4986 26856,9085 26858,9866 26859,9038 26863,9276 26865,4908 26867,9944 26871,6322 26873,5628 26877,7637 26880,5344 26885,5925 26889,4431 26890,7266 26893,9524 26897,9995 26901,10452 26904,6901 26905,7842 26909,10085 26912,7819 26916,8370 26920,4712 26923,5032 26927,7921 26932,8366 26937,5842 26938,6184 26940,10078 26941,4779 26943,10131 26945,4942 26950,5296 26954,6648 26958,8067 26960,9010 26964,9220 26968,5839 26972,5573 26975,9178 26979,6677 26984,4607 26989,9995 26990,7978 26993,5814 26996,6687 27000,7439 27002,6581 27004,8976 27007,8730 27010,8493 27013,5589 27014,9424 27016,7370 27017,5177 27018,8911 27022,4792 27027,10427 27029,4957 27033,10048 27037,5506 27040,8711 27043,9100 27048,6045 27049,7701 27053,4398 27055,5565 27056,4845 27061,7696 27065,7900 27070,7487 27072,5185 27073,5421 27078,7870 27083,4938 27088,9280 27090,9484 27092,5501 27095,5522 27099,7551 27100,9185 27104,6200 27107,9088 27112,8019 27117,8367 27121,6878 27125,5696 27128,7805 27133,8208 27136,7304 27139,7943 27141,4779 27146,8018 27151,10064 27154,9196 27157,7995 27162,5495 27166,7968 27168,7247 27170,5856 27175,5889 27176,5994 27180,4434 27181,6143 27185,5592 27190,8307 27191,6227 27193,5655 27194,8511 27195,8277 27198,4748 27200,4528 27204,6439 27206,7026 27207,5484 27211,9384 27215,6992 27219,6677 27222,9504 27223,5124 27226,7264 27231,5120 27236,7651 27238,10297 27240,6961 27243,8778 27248,10199 27253,6163 27255,8948 27258,8673 27261,10428 27266,6765 27269,9405 27271,6654 27274,9331 27278,10077 27279,10245 27284,7192 27286,5519 27291,8860 27295,9730 27300,9227 27303,10124 27305,4979 27308,7874 27310,8975 27311,5387 27315,7708 27319,5363 27321,6385 27322,4456 27327,5706 27330,5499 27332,9635 27335,6804 27338,6257 27343,7486 27345,10036 27350,5891 27355,6793 27356,5379 27358,8425 27362,7018 27367,5738 27368,7046 27373,9203 27376,7566 27379,8603 27381,5065 27383,5476 27385,9970 27387,4765 27389,10252 27394,7360 27397,8702 27400,5360 27401,8100 27402,6690 27405,6205 27410,6722 27412,8822 27416,9811 27418,5268 27422,10350 27427,6717 27432,9246 27437,6788 27439,8434 27444,4395 27446,9793 27450,7974 27452,5032 27457,4823 27462,6765 27464,5635 27469,6606 27471,7163 27475,5074 27478,9162 27480,7356 27482,10386 27484,7998 27486,9476 27489,9251 27490,6154 27494,9090 27498,4944 27499,6521 27501,6566 27503,9842 27507,7996 27510,4900 27512,10082 27514,4832 27517,7948 27522,5566 27526,9841 27531,9045 27533,8380 27536,4519 27540,10182 27544,4636 27547,10037 27548,5980 27551,7571 27552,10011 27553,7775 27557,7571 27560,4862 27565,6113 27570,6242 27574,9279 27579,5376 27581,6574 27584,6126 27585,9378 27588,7895 27593,9075 27594,4549 27595,8238 27600,7161 27604,10095 27609,4543 27612,9606 27613,7238 27617,5762 27618,8489 27619,6801 27624,9428 27626,6480 27628,4745 27633,5441 27638,4508 27641,5652 27644,9721 27649,6784 27652,5652 27653,9818 27658,9831 27659,9733 27661,7148 27663,8505 27668,5135 27672,8420 27675,8881 27676,6147 27677,7359 27680,7366 27683,9150 27685,6933 27687,6530 27688,8102 27691,10269 27696,4981 27701,9644 27705,6684 27707,8686 27712,6074 27717,7295 27720,8667 27725,7893 27730,4852 27733,4700 27736,8419 27739,8711 27740,4473 27744,9992 27745,7422 27748,8875 27753,10068 27757,5261 27761,5595 27762,4386 27764,6744 27765,9403 27766,4777 27770,8781 27772,7977 27774,6882 27776,8730 27780,7003 27785,6516 27789,8375 27792,6218 27795,8146 27800,10417 27802,5289 27805,4598 27810,4381 27814,7950 27819,5513 27820,6843 27823,10381 27828,10009 27831,7755 27836,8822 27838,10366 27843,10128 27847,4735 27850,4744 27855,6901 27859,9340 27862,9232 27866,8723 27870,7994 27874,9632 27878,5201 27881,5996 27882,10277 27886,4770 27888,6165 27891,6779 27892,10089 27895,7912 27897,6163 27902,9498 27903,9028 27904,4985 27906,10252 27907,7746 27909,6815 27913,6688 27914,6608 27919,9183 27921,5380 27924,7331 27927,4660 27930,9338 27932,7349 27934,5972 27939,10481 27941,5353 27945,6049 27950,10489 27954,10057 27956,8372 27958,9188 27963,8945 27966,8738 27970,9386 27973,7982 27977,10298 27981,6724 27982,5799 27986,10382 27991,5472 27995,5325 27997,7390 28002,10309 28003,9560 28007,8741 28010,9603 28015,6503 28020,7463 28021,5527 28025,4991 28027,7367 28028,6391 28032,6718 28036,4907 28038,6198 28039,4827 28042,9447 28043,9217 28045,4431 28049,4880 28054,10412 28059,5892 28062,8944 28067,6078 28069,9020 28071,9672 28073,8142 28077,5661 28080,7841 28084,7222 28086,6643 28087,7217 28091,7845 28096,8575 28099,8615 28103,9039 28107,6371 28111,7397 28113,9117 28115,7917 28120,10226 28122,7920 28124,8943 28129,10408 28134,7942 28135,10424 28137,9571 28138,5917 28141,7021 28144,7388 28147,9987 28152,5562 28155,5511 28156,7301 28159,5205 28162,9251 28165,4622 28167,5469 28168,9818 28171,6680 28176,4560 28177,7918 28179,8195 28180,6076 28185,10256 28190,9471 28193,6318 28196,5087 28199,7034 28204,10388 28208,8033 28213,7880 28215,7978 28219,10251 28220,7983 28222,6024 28225,9840 28227,4398 28228,7983 28231,4621 28233,5038 28236,7228 28241,7556 28242,9905 28243,9187 28248,7787 28251,5085 28256,8964 28258,9109 28263,6239 28266,8164 28267,9685 28270,7481 28274,8611 28277,4726 28281,6236 28286,4949 28289,5068 28293,9667 28297,6321 28301,6540 28305,5895 28307,9445 28311,5263 28313,5974 28316,4777 28318,4514 28322,7034 28323,8425 28325,7785 28328,8791 28329,8555 28330,5760 28335,10305 28338,9580 28340,4615 28344,5068 28346,6925 28349,5870 28353,8432 28358,10262 28363,10373 28368,8663 28372,8864 28377,5801 28381,7875 28384,9572 28386,7984 28390,8141 28394,5759 28395,6399 28398,6393 28403,5734 28407,8732 28409,9975 28414,7453 28417,7691 28419,9947 28422,8392 28427,5889 28431,9949 28434,6890 28438,9878 28443,9463 28446,9081 28451,10129 28453,10219 28456,6756 28457,6313 28461,4822 28465,8366 28466,9088 28467,5041 28472,5808 28475,10126 28477,7752 28479,10142 28484,9492 28485,7445 28490,6743 28492,4457 28496,9828 28501,8633 28505,8185 28506,7814 28509,10339 28514,5919 28516,4648 28519,7756 28524,7838 28529,8716 28531,7730 28536,8743 28537,6946 28538,4822 28541,9448 28542,7303 28544,8237 28546,7606 28549,8002 28551,6983 28552,7547 28553,9567 28555,6619 28558,8746 28562,4563 28565,8529 28566,10169 28569,9893 28573,7529 28578,9353 28581,9508 28583,7824 28587,6196 28591,5098 28594,6897 28596,8450 28598,6358 28603,9542 28607,6898 28612,6363 28617,5456 28620,5879 28624,7181 28625,9802 28630,7438 28634,8052 28636,5626 28641,5989 28642,9417 28645,7351 28648,7264 28652,4694 28656,10424 28661,6554 28665,8237 28669,5126 28674,5507 28679,8554 28684,6971 28688,5505 28690,10129 28694,4558 28698,6129 28702,9403 28706,5507 28707,8612 28709,8785 28713,5273 28715,8588 28717,5852 28722,5199 28726,8046 28728,10198 28731,7624 28734,7483 28739,9664 28741,6610 28746,9270 28750,7085 28751,6863 28755,9195 28760,6646 28763,10415 28765,8024 28770,4684 28775,4707 28780,6978 28781,7306 28785,6119 28789,5300 28792,5853 28794,8628 28799,9934 28801,10247 28805,8553 28808,7428 28809,9895 28812,8946 28813,9777 28817,9020 28821,5416 28826,6517 28829,9935 28831,5578 28834,5718 28836,9555 28839,4810 28840,8450 28843,5391 28845,9425 28847,5885 28851,6758 28854,9263 28859,7447 28861,4921 28865,7215 28868,9982 28870,8265 28873,6536 28878,5067 28879,6699 28880,4764 28882,5191 28884,8852 28885,9521 28890,7376 28894,6067 28899,7284 28902,8977 28905,9339 28906,6935 28908,6883 28913,5103 28918,5665 28923,9054 28927,8363 28929,9026 28934,10160 28938,5809 28941,4407 28942,7636 28947,10120 28948,9078 28950,8529 28955,9193 28958,8714 28959,4672 28963,5157 28964,6786 28966,9239 28968,5656 28971,4912 28975,8508 28978,7812 28979,5320 28980,8937 28985,9731 28987,8815 28990,6618 28991,6317 28996,8266 28997,6927 29001,8002 29005,9397 29009,6787 29010,7506 29014,9605 29018,8910 29020,5058 29024,6660 29029,7804 29034,8832 29037,5171 29038,8089 29041,5473 29045,7054 29047,8733 29048,7974 29053,6646 29057,5740 29058,6484 29060,5770 29061,9533 29063,4539 29068,9741 29071,9632 29074,6055 29076,7023 29080,5246 29081,9504 29084,7635 29089,8792 29090,8501 29092,9183 29097,6489 29102,7565 29104,9209 29105,8476 29109,7892 29111,5777 29115,8984 29116,7717 29121,7972 29124,6301 29127,5432 29128,5617 29131,5684 29133,6340 29134,7503 29138,7660 29139,5995 29141,9974 29143,7534 29148,6765 29149,6537 29153,7960 29157,7442 29159,10309 29161,6067 29165,8363 29166,9235 29168,9124 29171,4391 29175,9751 29178,9540 29180,9725 29182,10375 29183,8417 29186,8138 29191,6124 29194,5139 29199,7981 29201,7712 29205,6345 29209,8491 29212,5892 29215,6231 29218,4488 29222,4838 29223,9511 29225,8731 29227,8351 29232,8703 29236,8902 29238,9454 29243,8428 29244,7031 29248,10140 29250,9776 29251,8831 29256,10284 29259,10234 29261,10443 29264,7565 29265,5308 29268,7506 29269,6654 29274,6226 29277,7419 29282,6946 29286,7842 29287,7760 29289,10089 29293,8536 29298,7012 29300,7123 29302,7531 29306,10352 29309,5839 29312,4524 29314,7030 29319,4432 29324,6086 29325,4666 29329,9254 29333,9475 29336,9295 29337,4775 29339,4796 29340,10314 29343,6517 29345,4393 29346,7600 29348,5405 29350,9007 29353,10350 29357,9053 29358,5831 29360,5595 29365,6580 29368,4909 29373,9315 29376,7757 29377,4722 29380,9188 29383,5503 29386,4807 29389,4497 29393,10098 29398,7192 29402,7314 29404,7828 29407,7139 29412,8142 29413,8840 29414,6192 29415,6885 29417,10420 29418,7343 29421,5787 29426,5367 29430,5003 29432,8255 29433,10065 29438,6392 29442,8406 29445,4854 29448,8071 29450,9759 29453,5546 29455,6258 29457,8185 29462,6338 29464,8842 29467,10175 29472,10403 29474,8182 29479,10202 29484,5483 29489,6517 29490,8211 29495,6006 29499,8590 29503,8510 29508,7455 29509,8886 29511,10244 29515,10440 29520,8914 29521,7539 29526,5987 29528,6004 29532,6807 29534,8803 29539,6190 29542,10392 29545,8893 29549,9354 29552,9362 29553,8951 29557,7801 29562,9923 29564,10338 29565,8810 29568,9448 29570,8015 29574,10182 29579,10196 29584,9344 29589,9081 29594,6531 29597,8945 29598,5779 29603,7452 29606,10288 29610,5626 29611,7375 29613,6964 29616,5128 29617,4703 29621,10353 29625,6675 29630,9535 29635,8213 29638,7348 29639,10050 29640,8770 29645,6074 29646,9351 29649,8375 29652,10100 29657,4443 29660,9046 29662,4618 29665,5415 29666,6104 29670,6793 29673,9473 29676,9414 29677,4488 29678,6772 29683,8481 29688,6038 29692,5201 29695,4758 29697,6524 29698,5587 29701,5232 29703,9341 29706,6032 29709,7317 29714,5550 29718,6226 29722,5179 29724,9282 29725,10262 29726,5669 29730,9493 29734,4740 29739,9193 29742,8608 29747,9091 29748,6358 29753,6836 29757,10047 29762,7418 29764,5077 29766,7175 29771,5633 29775,6774 29778,7731 29779,5792 29781,5382 29783,4915 29784,7952 29789,4869 29794,9085 29799,10242 29804,4482 29807,6948 29811,7985 29816,5607 29819,4546 29821,6979 29824,4852 29827,6907 29828,7472 29832,6831 29834,8427 29836,9623 29841,6221 29845,5479 29849,7314 29852,5573 29857,7174 29858,8518 29861,6078 29862,6739 29865,8170 29868,4793 29869,5131 29872,5478 29875,6693 29880,8374 29885,7272 29889,9584 29893,8493 29898,7833 29900,8738 29904,8793 29905,4417 29906,8581 29907,4820 29908,6902 29909,5318 29913,4535 29914,5256 29917,8220 29922,5105 29925,5928 29926,9740 29928,6048 29933,5726 29938,7276 29942,5767 29945,9577 29948,4977 29951,8927 29955,9804 29956,4527 29961,8419 29965,6430 29967,5482 29969,7994 29971,8517 29973,8984 29975,5208 29980,5215 29981,8303 29982,7987 29987,7626 29992,5919 29993,8406 29997,6463 29999,9620 30003,9854 30004,8275 30007,9863 30012,9379 30017,8257 30019,9078 30023,5166 30026,9612 30029,5462 30030,8779 30033,7496 30037,5990 30038,9448 30041,7451 30043,5822 30045,7593 30047,10273 30050,6538 30052,5657 30053,6318 30057,7783 30059,7521 30064,9013 30065,9641 30070,5794 30071,9870 30073,6535 30074,9895 30076,5989 30078,6032 30081,6455 30084,7316 30086,5942 30090,7999 30092,9477 30094,6848 30097,7896 30099,8173 30104,8941 30109,5828 30112,4828 30115,5435 30118,9009 30121,6860 30126,9902 30128,7913 30132,8559 30135,7994 30139,10273 30141,8918 30143,8774 30147,8964 30151,5529 30154,7216 30157,6470 30158,9489 30161,9564 30162,4670 30167,7951 30170,4847 30174,10146 30175,4853 30176,7808 30180,9926 30181,4800 30186,6660 30189,4881 30190,10287 30194,9331 30198,8484 30201,4385 30203,7680 30206,5654 30211,6713 30215,4389 30216,5408 30220,9176 30221,9343 30226,4879 30230,8507 ================================================ FILE: tidb/join/t/r1.tbl ================================================ 1,4363123,46773,6709 2,1431076,902781,8246 4,2792150,84359,8209 8,4966517,375246,7436 9,10590291,822710,6358 14,5452431,156645,6256 18,1472948,617365,7746 22,5744270,262657,6826 24,7539335,147699,7384 25,126086,408508,7021 27,146482,719153,6395 30,2000764,373418,8822 34,7481826,890926,9733 35,8460579,712881,7020 37,5351465,246250,7677 38,358942,756258,6785 39,9873954,61813,10321 41,8347988,595273,10684 43,3202180,711137,7256 45,8265445,755763,9049 49,3109466,588588,5664 52,2491113,418820,5740 57,440430,640732,7680 60,437959,773452,6236 61,2119773,233270,8540 64,5276326,317610,7586 66,1592615,346750,10098 67,3423590,28395,7170 69,2304616,582963,10247 73,656785,21983,6703 78,716489,606054,7210 79,2192181,891170,9874 81,4316773,326507,6248 86,3982691,650383,7980 91,1812229,74183,8270 95,5567934,761395,7110 98,3179472,396854,8010 103,8020025,797932,9044 107,8728673,697585,6376 108,6471797,112370,7063 109,4414796,165203,8276 110,6652760,859201,7329 112,4805559,730490,9272 113,7126477,57554,8140 116,4356735,674060,9639 119,10313921,511552,7685 122,2297921,680825,9733 123,4596887,636006,7724 125,436116,365137,9793 127,5588735,216726,9349 129,3018350,796987,9203 130,9198929,504967,6798 133,5285566,339974,6902 134,2755673,623233,8576 135,10381811,168301,5962 139,1625685,483223,7921 142,10150457,470757,5658 145,7590313,411865,6077 150,6016620,471865,8467 151,22727,626003,9715 152,4314459,898370,8784 153,7829051,596832,6100 154,10465374,657760,8900 156,2087645,437523,8490 159,9921676,885044,9226 161,10225398,352806,8404 164,7213028,227292,10675 167,1929131,222810,6625 171,6103926,287482,7292 174,6630303,534964,9656 175,7415477,79789,7010 177,7212232,829714,8110 178,9522330,91297,7661 182,3324270,17954,10152 187,9549194,533329,10443 190,280273,435370,9730 195,9580632,360760,9826 200,8270700,86157,9294 203,7798317,80383,9274 207,1722041,582628,6024 212,5366493,504678,7311 217,7904095,128100,10104 220,263778,716380,6717 221,816942,374851,8768 222,10411057,486545,9568 223,6645372,924205,6188 228,2837449,623073,7917 232,5218670,389052,7736 234,7224272,101473,7281 239,9601935,462729,9638 244,5386123,590982,7982 249,1251800,486976,10200 251,10234131,185140,6669 256,2973356,223024,9949 260,1790026,399413,6410 263,3920508,545498,9187 264,4221626,697378,6226 265,4186384,135411,7841 267,2650240,115507,8265 270,10534226,346725,8320 272,653016,913727,5914 277,2961953,29992,8038 279,6921583,350504,7525 280,6747316,514822,9373 282,4168373,799801,6468 284,6564602,583565,8633 286,9916034,175801,5771 287,9256308,112613,6837 292,8233638,458198,8644 293,316851,184553,9658 296,1713971,262131,6878 299,5443681,446679,7560 301,3904295,716606,9691 306,8053875,436079,9279 307,2467940,192526,10073 310,7519669,796886,8399 315,3529324,492750,7576 319,1199145,508173,7344 323,2191346,85130,7156 324,4459918,686798,7145 328,7467816,630445,5968 329,5181283,534199,9826 331,8951483,600507,9464 335,973283,906685,7709 336,2915908,732320,7341 340,6727354,354415,8492 343,9163124,880526,10270 346,7172090,335468,10255 349,7506996,407610,6456 354,2240520,759092,7809 359,6408119,562593,7374 364,10659664,204943,9427 369,10609588,668542,7917 373,2530741,496999,8983 375,3590704,859329,9114 379,7137600,377534,10663 380,9267678,581337,7044 385,6928556,452561,6114 390,6997731,91157,6434 395,6512076,743232,9093 398,7334624,752384,5733 400,10233377,829696,8676 401,2669625,504132,9924 403,943994,176403,9996 405,796693,247572,10462 407,6315795,862308,7605 412,7118004,609029,6961 416,9637422,818715,9747 418,4170178,530839,6737 422,7472357,417486,6903 424,3190188,505009,5702 426,5835401,341125,6394 429,1915566,573569,8985 432,9513111,403337,6074 436,3025202,217531,8751 440,5793013,865055,10589 442,8218240,199010,9151 443,5598863,572557,6737 448,6738084,67608,6846 452,9295926,560464,10347 456,8915704,513500,10019 459,1978665,151057,6996 462,7067870,54318,7188 465,2234910,356679,6263 466,2157048,55067,9257 471,6407073,107313,10374 476,4688293,851415,8110 480,6658747,82179,7318 485,8508198,93311,10293 490,10326628,420692,9842 492,4404746,745556,8456 496,7266335,224423,8980 501,4937096,793005,6101 502,715986,337861,6846 507,5384318,819571,8945 509,6346991,577171,10105 511,6991144,388035,6019 515,2065958,521130,7871 519,4777277,209933,7048 521,4440943,819505,5617 526,4328862,588014,10203 527,1006513,24735,10694 529,1128270,490557,8468 534,8385177,685583,8041 538,357950,407908,10475 543,3177970,53564,8358 544,2260528,876834,9328 545,4175921,429662,6266 546,9638952,488553,5772 551,10000198,426038,6972 556,5342669,374722,5703 559,407880,383879,8619 564,9733718,291178,6553 566,4180354,422778,10237 571,7886388,747454,8195 575,100448,713024,6700 578,1650967,120109,8331 581,5970993,309305,9080 584,5776992,261845,6159 589,6481698,375225,9757 592,7542704,887471,8391 596,9718801,633110,8871 599,6750559,91993,5937 604,116510,861222,8153 605,9825788,871756,6762 609,5719176,763400,7145 610,4241752,334685,9615 614,1397184,318290,10040 616,2381952,317183,9194 618,2514934,76122,8885 621,2375594,268274,10694 625,6220379,455394,7790 627,542248,153942,6774 629,3472743,784254,10270 634,9512787,123971,7191 639,5263073,429522,7934 641,2324332,411824,10191 642,10434132,391438,10388 647,7447041,174141,6591 650,8344620,321219,6079 651,1174946,706295,6241 655,1088883,211316,6578 656,9064954,910709,7787 659,4942912,900115,8515 662,4958934,496639,5777 666,8944674,707592,9338 670,6153457,280438,7335 675,2813565,626988,6612 677,4680662,868406,10626 682,7394380,259762,8543 684,1650290,357501,8924 685,752595,178628,10363 687,6551835,159665,8275 692,5233370,271438,8098 697,8435385,416352,8756 702,5476840,188083,9257 705,3896141,579523,8199 707,6098943,282971,6258 711,2697887,692652,7817 715,6789750,238485,7220 719,10015474,857513,6000 720,726486,477789,7308 724,6662310,876579,9000 727,2642776,895582,7874 730,2526176,303108,7001 731,7671902,593342,5988 735,2975504,520367,9379 738,6099838,104988,9223 743,9678267,571657,6630 744,10203330,640706,5642 746,3053196,304139,9463 750,1006084,608205,7244 754,10337708,254904,6360 757,375738,771819,10016 760,4369712,919063,6860 764,8347196,409392,9021 768,9041481,876834,5733 772,5102077,157606,10648 777,2608061,353143,8153 782,995724,455833,10236 783,7684940,896762,7855 787,3533733,315988,5860 789,8263390,210099,9073 794,5331922,287746,7551 799,5836423,704052,9486 803,7145813,78164,9873 804,6565098,128022,6595 808,4140553,626751,7483 809,10418232,780755,5772 811,7645122,293993,9297 813,151174,248535,7288 818,1259165,67028,6276 822,875772,347479,9055 825,6557177,459969,9452 827,1558606,837033,6226 832,3315315,783431,5631 834,2427752,400110,7029 835,3902769,193672,5907 838,4882469,855579,7979 841,9088014,779310,7855 845,1484133,935475,5728 849,6731120,464016,8226 851,5675433,153141,10367 856,6503353,513513,6527 857,3655065,405498,9511 861,7233164,29597,6712 866,9426743,341199,6566 869,3602094,215377,9703 872,9360268,465277,7626 876,6139520,914715,8228 881,9868424,822460,9456 883,3178971,893850,5872 886,9742604,58319,10647 888,7482862,164889,5628 891,10050840,792375,8143 892,4493777,34599,7268 895,3504818,572889,7452 898,7559016,741310,6719 900,1220939,608366,7159 903,5069093,495448,8766 908,4296969,921618,6027 910,6822716,83488,9660 912,3930073,366545,10104 914,3074131,400518,9208 916,7460654,201083,5859 919,881577,495396,9076 924,9890555,736983,9420 928,1409158,591133,7741 933,5222491,487495,7743 938,5602465,834126,8239 941,2341915,94338,9520 946,5288395,423820,8679 949,1784242,185732,7733 954,10243846,369906,9017 958,10626225,883602,8519 963,8246053,460835,6996 965,2720062,520215,5830 969,7627168,877473,8104 971,10598798,448449,7777 974,3294761,296962,7543 978,8290646,484578,6240 980,6000011,43874,9828 983,4285404,136477,9088 987,5119596,33225,9287 991,1838497,855733,8837 993,6803501,316693,7919 996,1208186,212032,8217 997,7865934,616305,7215 998,8741895,914259,8362 1000,8221761,701317,6349 1001,495175,432536,8156 1002,9066860,895116,6068 1003,10113544,61864,9998 1006,2379298,135398,6859 1009,7290223,227152,9504 1013,4183853,913571,8163 1017,9712856,121778,5747 1020,9653741,391402,10289 1024,10500733,760329,8305 1025,4300175,197628,9527 1026,6916870,61041,7822 1029,845344,408782,5740 1032,10291093,394699,10027 1037,5853235,525591,8148 1040,5037730,14873,8293 1045,9381834,262880,8183 1047,2320410,805596,10126 1052,1477620,68686,9900 1056,7739230,616456,10115 1059,1981750,88074,7403 1064,2421317,130829,7522 1065,7281798,707544,7466 1067,8961454,396832,7794 1071,6934458,861798,7093 1074,2462965,636748,10365 1079,5766235,835438,7403 1082,6170645,861974,9982 1085,650050,492441,6807 1090,9694556,936002,6720 1092,2335987,590437,10108 1096,4106529,361014,9016 1099,2441106,457485,5856 1103,10511249,143105,8111 1106,1301976,594819,10505 1107,5158135,847376,10065 1111,6672184,203160,7548 1115,4512258,115692,8034 1116,1766372,266050,6728 1117,6448660,829506,9710 1122,6267434,323265,7906 1126,7064724,498907,10233 1127,7200383,266333,10347 1130,5029974,785064,6562 1133,1718854,125473,9712 1136,8860700,787469,6615 1141,8126408,691306,9579 1142,4691262,2873,8119 1145,9334686,788932,5910 1149,7151802,731843,8705 1154,8775087,750436,9431 1159,5109950,125725,6098 1163,5656230,674111,9518 1167,4669637,103500,6848 1169,3623181,733693,9135 1172,1190057,824128,10356 1175,661058,19955,8927 1179,6289199,527954,9887 1180,706125,341508,9591 1183,1424724,841030,7566 1185,7241205,838206,7561 1189,918585,225922,5717 1190,6719918,679186,8137 1194,8497203,173829,7599 1195,5865441,424876,8921 1199,8147287,810220,7821 1200,870698,156829,8306 1201,5703143,119010,9417 1205,2520134,88808,10029 1207,2151930,820215,6434 1208,8233189,87013,7166 1210,3625389,219750,9894 1215,2340068,417774,8852 1217,8260369,11801,8836 1221,2964639,81926,8893 1222,4361888,857807,10510 1223,6304201,319236,7967 1227,5243216,551300,9857 1231,1200834,868050,6580 1236,9119671,600293,10195 1241,623250,583349,9837 1244,6765716,324884,6607 1246,6851804,580377,8953 1247,2165049,843366,6849 1252,3872866,225183,8112 1255,4925102,796306,10164 1259,2916985,538680,6339 1263,3606727,724884,9521 1268,3703651,64715,10394 1272,5124750,825176,6550 1277,3611397,11910,6693 1279,7610869,709942,10373 1284,1880715,225933,9062 1287,10611500,583826,6900 1292,2141204,357151,7698 1295,1467542,215548,8208 1296,4244900,177487,10550 1301,7988093,158217,7500 1304,8457377,414571,6856 1309,10600045,2880,10335 1312,9330890,296696,8633 1316,1423536,453104,9008 1319,360235,451394,8907 1322,5909307,732264,6540 1324,3894870,11182,6527 1326,3970228,245337,7895 1329,9096074,511427,9556 1334,10472254,127253,8793 1338,9807631,925993,6730 1339,10220083,83235,9900 1344,2579998,158,7425 1348,8246385,445053,7315 1350,6699151,694192,7102 1352,592187,35908,8050 1353,2924186,475141,7353 1356,620701,178219,7498 1360,3819348,798219,9659 1363,5164062,822140,8672 1366,2135874,813235,8826 1370,8129493,805462,6798 1372,3445876,96077,10219 1376,10380845,107878,7265 1377,273780,186871,9126 1381,10472393,194780,8181 1384,10006632,87942,9960 1389,4448169,52964,6742 1390,7736080,456844,10354 1391,2981895,759217,8771 1394,5982579,585255,8818 1398,6947480,27432,7275 1400,452002,663862,6727 1404,1008282,333244,7245 1408,6805537,119256,6333 1413,3674889,692305,7141 1414,6500378,364236,10471 1418,4773336,919232,6737 1422,305291,594559,6542 1424,8928504,87116,7676 1425,3007480,480519,8332 1426,1609490,648293,5800 1427,9527858,216365,7738 1431,3565504,31958,9266 1435,9035592,106482,9690 1437,3937402,882578,5742 1442,5174661,834923,8382 1447,8387652,818750,7015 1448,4012300,742341,9734 1450,7341564,51889,10352 1455,2364325,574675,8760 1457,2801309,77110,7858 1461,3863882,204722,9632 1463,6889608,288898,10539 1467,4137288,560424,5638 1470,5600305,919105,7121 1472,4502184,115539,9123 1476,9721940,796853,6376 1479,9830835,1123,8497 1481,519046,828892,8830 1482,10043646,536066,7521 1483,5795458,397794,10416 1487,6639419,490802,6186 1491,368423,203999,7677 1492,7476271,515295,7715 1495,2916891,541121,7208 1496,3653159,514364,7736 1498,2153006,98242,9300 1502,5623737,106347,6892 1506,10418706,376228,9652 1507,1885168,494601,8962 1512,1055301,466964,6711 1516,9921727,864686,8240 1518,6545437,613322,10507 1523,6884765,699054,6408 1524,5209471,251687,8074 1525,237519,252674,6209 1526,8808199,176468,8422 1531,9222735,755791,5944 1533,2394489,473452,5750 1535,7384767,918585,8545 1537,1096290,615358,6913 1540,9575415,414360,5702 1541,8511450,443396,10334 1542,994046,596936,9204 1547,2099689,491721,8242 1552,1361505,309028,8371 1555,2669900,514963,6143 1556,6096723,550136,6148 1558,8027708,686693,9683 1562,3207451,565945,10311 1566,10649498,697398,6892 1570,2934882,773636,6402 1571,2078825,771574,7740 1573,8396831,286727,8763 1576,8564372,854620,10462 1580,1883438,791001,7831 1584,1323431,289124,9856 1585,6078649,651164,8608 1590,4836830,492406,5717 1591,4801446,1032,9855 1592,1652135,342004,6716 1595,6356398,861614,8964 1597,8821462,45652,8411 1601,365435,873558,6099 1602,7971792,732504,5901 1607,9586193,495011,7926 1612,7194075,483981,10036 1617,6593509,599667,5627 1621,4942015,29141,9103 1626,8286450,290670,5734 1630,8369496,921491,8512 1633,7878723,499675,9426 1635,1217502,745863,6902 1639,5139242,777957,8127 1642,9577204,320618,10650 1645,6578540,522423,10010 1646,4672013,6088,5795 1648,6220952,53509,6326 1651,5505334,605321,9853 1652,6053794,420439,9322 1653,3754991,61041,9060 1657,2948397,607924,7395 1659,7526085,472041,8159 1660,2751725,925767,7373 1662,4016884,927076,6472 1664,7202228,54087,9397 1665,9994558,357998,9357 1668,6149420,776945,9059 1673,7638354,691904,6790 1675,7981773,44487,10509 1679,2086296,778133,7915 1682,671085,99189,8669 1686,6832746,249297,5738 1691,136953,888469,8951 1694,6534082,580950,7372 1697,10271483,853762,7657 1699,2633012,310296,10356 1704,10466894,136164,9278 1705,7192757,363940,10304 1710,10471653,937456,7360 1715,68067,584476,8239 1717,5021850,230501,6266 1722,1718790,511331,6904 1723,7300792,203029,8500 1724,10369597,480620,7901 1728,8810839,770592,7255 1731,3841080,214952,8905 1732,1983890,886024,6825 1737,7391415,895615,9408 1739,348806,455435,9289 1740,10528612,90485,10046 1742,4328463,845346,6272 1745,397270,84249,7246 1747,3275023,95568,9277 1751,8130739,725121,6407 1755,4791668,82764,10407 1756,10521470,321699,8470 1759,8444894,621832,7968 1762,7715290,526708,8740 1767,849688,80484,7756 1770,9711611,523726,7007 1775,7104972,747088,10322 1777,74261,330620,9753 1781,8561882,1794,9442 1782,3474658,313515,6877 1786,2959912,418323,10075 1787,2095669,788090,8501 1789,3180199,269535,9338 1794,5130621,668855,10621 1795,7098676,787364,7226 1800,8444670,892891,8459 1803,1236370,807861,7135 1806,1832761,525935,7598 1810,8593035,211806,9878 1812,4833862,502163,8892 1817,8387484,304440,8984 1820,1930426,172501,7965 1823,3789380,767351,8146 1828,5348388,593123,7000 1830,8157553,417227,10214 1833,7395321,64638,10299 1838,178646,776811,7077 1843,9248746,316774,9517 1847,6475880,457251,7119 1851,5404594,351010,9677 1853,5079320,935753,7979 1855,10562271,886887,9459 1860,1038961,136059,8959 1865,2003770,572297,10056 1866,1091778,98432,8491 1867,8415565,279494,7119 1869,3803427,91504,8345 1870,2292865,476572,6087 1871,6864477,814749,7073 1874,4872639,73311,10618 1876,6472040,539765,8500 1880,6395056,902433,6195 1881,6241646,379220,9728 1886,5280882,368731,6635 1890,9621278,289020,9209 1894,3278785,475353,7675 1896,2842574,448709,6539 1898,8220837,613717,8891 1902,4190642,490689,6815 1905,2571926,334093,8422 1909,5988490,420578,5798 1914,8120848,857163,8678 1919,5293700,301713,7631 1921,8035898,205715,7352 1922,4397314,504456,7215 1926,10303337,716796,6353 1927,946156,125729,7571 1931,7103912,666674,7350 1936,10435946,36354,8572 1937,1285277,579441,9723 1940,3853045,709666,7208 1941,4388814,848215,8335 1946,515434,869190,7245 1951,2706286,505448,10095 1956,5587454,547577,6539 1961,446830,490217,7546 1966,8828498,130224,5668 1968,804914,68566,9555 1970,8976176,353532,7545 1975,1397997,807513,8188 1976,5961607,933910,10626 1979,1275439,87892,8199 1984,261079,95940,10405 1986,4916654,24522,9542 1991,4712363,629022,7031 1996,8638475,401903,7440 1997,1834071,219671,8357 2002,10152267,764953,6252 2005,6378883,355246,10309 2010,1105805,834700,7791 2012,3596450,111245,7506 2015,7898792,156111,10230 2016,6267804,173661,10253 2017,9661525,408321,5967 2019,5035534,594016,7047 2022,1116818,925940,10013 2023,3591440,814775,9677 2026,4426608,914158,6043 2029,9060921,660063,6650 2034,3505808,238569,8177 2036,6491232,514648,6519 2038,346180,84036,10184 2043,1376614,740310,7160 2047,620990,359074,8473 2050,7563978,699933,10112 2052,9560341,197970,8066 2057,2788831,181416,7014 2060,379528,255455,8632 2061,10638259,614650,8118 2066,9701252,868194,9480 2067,10287509,642872,6676 2071,692878,663283,8803 2072,4486334,343555,7060 2076,1751063,742486,6436 2081,2867822,376132,6774 2083,10185819,70807,9620 2086,7531279,390393,7717 2089,9796888,932280,8722 2094,5437336,474272,7998 2098,4223312,538153,10226 2103,7154323,229587,8044 2106,5250642,349236,7052 2109,1630113,262412,8399 2112,10641436,598956,6266 2116,4236133,333543,6998 2120,5192258,86641,7007 2125,5782312,516886,8339 2130,5338041,785350,10087 2135,3953888,806471,9955 2136,6593257,278864,10079 2140,9799633,144879,9122 2144,7527671,547406,6498 2149,2697497,802748,9260 2154,10478851,71173,6012 2159,8548033,276774,9300 2160,5213140,558196,9424 2163,4250230,819651,5750 2164,4826308,362583,6038 2166,3674598,665335,6928 2167,6676785,498075,6042 2168,3372805,430773,8377 2172,4048442,403727,7971 2175,1963402,261643,6432 2178,1241631,168710,7057 2179,10242642,354027,5840 2184,2475761,560804,10595 2185,1817469,199410,8710 2186,4776555,900983,10440 2191,6945545,398991,7910 2195,8669906,187863,10394 2200,4919103,207527,9782 2205,139625,4484,8342 2210,4470847,28477,9756 2212,1846438,99891,6584 2214,6552473,556053,9919 2217,6492930,467688,7310 2220,1602660,752036,7728 2223,5952875,699891,9729 2227,7940391,192091,9006 2230,5800445,844123,6692 2231,5744003,617471,8566 2233,974353,695637,7252 2235,2210372,894225,10175 2239,6273146,131959,8698 2243,3776808,643495,10678 2247,4370150,590988,9200 2252,3118375,452310,9904 2253,3692568,636832,5751 2257,7962349,883346,8485 2258,5243869,626171,9252 2260,6772089,571106,5909 2261,5430220,21731,9189 2266,4373538,137376,8660 2269,2921275,156703,7905 2271,6900181,10784,8107 2274,9326669,409374,6953 2276,7028353,351001,8368 2281,10474975,626473,5846 2284,10233524,786781,5769 2287,3552230,609368,8908 2289,517461,376773,7478 2292,9597353,653820,10447 2293,9587592,29725,8405 2296,6948493,557381,6478 2297,1857096,426058,7687 2300,1807619,49443,8688 2301,7304655,97610,6967 2302,5554672,209464,9187 2307,2291109,534687,6798 2311,5598137,927350,5854 2312,2113492,549870,8991 2314,2315818,836967,10599 2316,7834047,251703,6195 2317,998295,237575,9820 2322,10523114,820528,6704 2323,9030422,606612,7209 2324,4245602,783384,10193 2326,5170816,195197,8902 2328,4926999,127578,6764 2332,6531406,794256,9185 2337,6582396,503417,9172 2339,1382265,142414,8125 2341,3755837,152868,9830 2346,4662986,857553,8914 2349,9320238,165129,6032 2353,4153555,311409,9095 2357,2816142,304920,7748 2358,8611483,884602,9552 2363,988939,422642,6912 2368,9443422,504331,5846 2371,9974391,475034,6866 2373,3024907,12361,5639 2377,4253196,287106,8055 2379,4472652,20100,5987 2382,10192514,305299,7509 2384,5480790,780040,6552 2388,2998353,642403,8292 2390,4126236,635735,8539 2393,4607159,581516,9216 2397,6796351,726212,7733 2400,2539155,264429,9367 2403,311563,457719,7625 2406,10224779,598693,9151 2407,6306050,231336,6985 2411,6627542,667329,7783 2416,9872896,181053,5962 2419,2243403,542899,7678 2420,7160061,623651,8008 2421,8063796,105943,6691 2426,9638334,66162,5854 2429,9186818,390739,5682 2433,1356397,938485,7516 2434,3419804,394897,6791 2438,2654244,619974,6085 2443,3203223,762150,7277 2444,4179938,83117,8239 2448,9631656,335003,9878 2453,9788815,653299,5914 2455,8956985,511890,8344 2458,9526274,342976,6598 2462,1618874,268548,8328 2463,3295122,460864,10581 2468,499938,282471,6467 2472,9783936,574540,6583 2473,2737388,275533,10452 2475,4096862,164840,8395 2478,2823144,298165,10377 2479,6620820,248638,8244 2484,7126638,581210,8760 2487,8570330,29116,7290 2488,7459782,711448,10570 2490,4243311,846578,9238 2494,5853082,773195,7323 2495,5180492,831578,8866 2497,4925851,185754,8013 2499,2666007,94134,5758 2503,10020694,552478,10111 2507,10014140,585338,6046 2509,4836829,445046,7293 2513,7502814,50363,9670 2514,7823064,479210,6983 2515,8739192,657882,7637 2520,1064330,434016,7929 2521,6713638,406758,9042 2523,2605230,177478,7250 2527,5671944,741029,6763 2529,236838,144341,8061 2532,7716990,374714,8318 2537,9250693,519817,10624 2542,610942,914244,7256 2545,6285804,786962,9028 2546,3023064,758205,10212 2549,252510,268321,7430 2552,551729,627768,5753 2555,6533226,751924,5917 2560,3824304,902644,8771 2565,6570495,206972,6225 2567,10262034,606372,5674 2568,8443384,708781,8400 2571,1936894,572220,8202 2576,6566700,676907,8484 2579,1777157,718054,9716 2580,5150861,354749,10411 2585,9027960,328143,9144 2587,4631423,250144,8654 2589,10104000,224255,10397 2592,1286630,539681,10196 2597,185373,824238,9516 2598,5259420,721940,6997 2602,8935775,248118,7618 2607,6523047,156320,8293 2609,7289068,202304,8901 2614,4636764,313383,6028 2619,2977102,158898,7526 2624,6840792,856466,7274 2627,4750128,790297,8306 2629,9479736,249807,7486 2631,4912636,180111,9337 2635,9218801,542113,8236 2637,6506226,782617,6329 2639,765159,583450,8549 2641,2185537,823267,8752 2644,2225422,724029,7367 2648,4672551,376925,10678 2650,3890202,241,10358 2655,8732717,519986,9460 2659,753733,691376,5925 2663,10030941,916954,5864 2666,10305523,191021,8051 2667,5243868,396805,6618 2668,4068049,136477,9702 2669,9617890,376874,5700 2674,7640236,270741,5684 2677,8657412,318678,6900 2678,10254203,543978,10241 2681,8873011,899701,6525 2684,4635799,791516,8004 2685,10580397,912873,7453 2689,4858403,196485,6449 2690,5688273,74769,6950 2694,3268859,547876,6207 2696,10098513,392416,8624 2700,446583,350041,9310 2702,6246634,902251,7255 2706,9736537,276294,7737 2711,2522528,74319,7754 2714,4381432,373734,8715 2716,3222629,163550,10420 2721,9625059,609317,10451 2722,5002226,386708,6673 2725,10480898,499203,7687 2728,2942610,73985,9759 2733,9099152,151039,7739 2735,980342,300684,7067 2736,8184164,720066,6327 2740,10431269,888753,6723 2741,4309702,414406,10461 2746,1504075,479953,8799 2750,9853626,680519,9975 2753,4087425,366536,6155 2755,1411897,922180,6830 2758,10259840,815423,10026 2763,4012950,651921,5711 2766,2561155,346520,10158 2768,1132129,518008,9222 2770,4487313,19518,7536 2774,6349996,270175,8577 2778,8868624,884216,9518 2782,630701,424843,10558 2785,4814691,73047,8599 2790,8710625,922634,10529 2791,6875833,450171,9416 2795,9738852,876011,6312 2796,1352904,28213,6979 2797,6248897,519071,8457 2798,3353286,821748,8765 2801,9898702,215069,9736 2802,9336477,270221,6435 2805,5084268,850597,10307 2810,3540425,445398,7075 2814,8840141,475989,7238 2818,7895300,69284,7715 2820,1472900,200410,6559 2821,7305201,350002,6858 2822,4509126,49447,6986 2824,7741890,766460,5964 2825,5885387,701083,8974 2826,3187625,484745,9392 2827,9228933,691638,9668 2831,1314273,348377,7723 2836,3621498,481378,8416 2838,1360081,504908,10496 2839,5163711,361448,8918 2840,415269,741888,8926 2841,1153042,389595,7263 2843,8885149,802025,8596 2846,3726746,69622,10486 2849,1087826,911391,9174 2851,10035592,673067,5879 2854,6982788,828082,8992 2855,4270,685520,5661 2857,8300355,712053,9754 2860,10193328,607921,5660 2862,67477,716096,5716 2863,5656092,787033,8502 2864,4111594,329509,6934 2867,1049548,428479,9114 2871,2385887,248285,8402 2876,4734470,786871,10612 2877,113283,567126,7050 2881,9321192,363787,8393 2885,2856164,337993,10300 2888,5622767,474774,8548 2892,4707350,578682,6678 2894,18668,628605,5812 2899,9228909,703490,9832 2903,3239390,612754,6318 2904,4800825,564924,9848 2909,2317793,170383,10489 2913,994262,319448,6538 2917,1158324,299592,6918 2918,7948260,633404,8032 2920,1965971,667354,10602 2921,7612388,230304,9819 2924,4973374,561119,7899 2926,8647557,916389,7521 2928,4028965,293385,9381 2933,7563571,911249,7758 2937,5332298,722508,10568 2940,6812916,636611,9610 2945,5681978,475771,8376 2947,3760793,106639,5714 2948,4166856,460952,10389 2952,7112470,623972,7010 2956,10547348,267576,7650 2960,5792634,797757,8010 2961,1040105,359509,9304 2963,6820561,632734,9930 2964,9117706,352735,10448 2967,3376332,142916,6809 2971,4619778,714358,10293 2972,5377555,201711,5892 2975,6194873,348253,9372 2977,6733436,728253,10358 2982,1462072,245207,9663 2985,7401907,780919,9060 2986,5648639,840197,6952 2988,1601267,803230,9390 2989,7934235,923154,7004 2993,5867856,12959,5833 2995,5077837,356491,9008 2998,9959762,619974,7736 3002,3482606,397957,8684 3006,3196984,621226,8516 3011,4383815,301832,6622 3015,437271,237127,9304 3017,9334553,21798,7405 3020,7490532,818798,5931 3025,241580,784360,8009 3029,3084435,420705,7987 3030,4924020,589261,8334 3031,2837922,382083,10270 3033,3274709,349405,7208 3038,10060913,879424,9160 3041,3807945,218856,7911 3043,7877211,398180,10152 3046,5267278,244186,6186 3049,7372530,431304,10155 3051,1378130,731360,6233 3053,1232146,741793,10441 3057,516443,284749,9933 3058,319838,397400,7142 3059,978270,639127,9666 3064,6966490,876628,9600 3069,601046,319988,8870 3074,8348402,748366,7784 3077,1281929,252506,10146 3080,912204,813565,7806 3085,2039911,891502,9045 3090,6716523,210443,9660 3094,613932,351160,7053 3097,945854,773308,9483 3098,3710047,24243,6852 3100,574574,455572,9371 3102,5310073,225398,7024 3105,5804950,898853,8487 3106,7531726,531089,10183 3107,10231971,197927,8546 3110,7337885,721175,6294 3114,2261573,455188,10192 3115,5777684,133632,8887 3119,3834019,524055,8460 3120,4654695,466391,7660 3122,2224426,862994,5661 3127,5489313,410659,6017 3129,7581472,736737,8878 3134,1237843,612682,9832 3138,9265094,125377,7909 3141,7314764,842307,9274 3143,4516522,23670,5915 3148,4517705,272001,7023 3152,795357,281908,6687 3154,1033148,214369,6028 3157,300245,420159,5688 3161,3300022,356694,10448 3164,446385,124051,9666 3165,9507376,749429,6475 3170,4025355,712495,7846 3173,1698529,865314,10553 3176,7239262,555525,8703 3180,5719586,428372,9922 3185,690733,481980,6083 3189,1791257,14994,8974 3190,5894370,441451,5767 3195,9399768,765944,6526 3198,8049522,49980,8563 3202,5020753,553170,6996 3207,887685,236604,5833 3212,4451550,754,9691 3214,3048533,728206,5946 3216,7908631,821640,7602 3218,3314331,128644,10516 3220,1448904,425368,6701 3222,570322,591954,9220 3226,8956473,920800,6865 3230,7978070,740403,8263 3235,3734932,272612,7548 3239,2904730,368947,7242 3242,8070487,716482,6870 3246,177976,154842,9461 3247,3895211,391820,7412 3248,10261218,426581,9529 3253,8367478,629039,7811 3258,6207826,273607,7137 3262,108394,596154,7707 3266,1348311,192377,10526 3268,2462742,861270,10588 3273,9226489,906851,9681 3274,2563826,930706,8036 3278,2765636,142837,8184 3281,848854,138114,9981 3283,6226907,115989,9200 3287,9581561,803732,9164 3290,9654576,605191,6527 3291,2883246,901044,7705 3295,8504712,516964,6368 3299,3804494,19279,8565 3303,8217727,36783,9630 3304,525526,809078,7660 3305,5910324,99756,9889 3308,8561792,530182,5698 3310,10229512,783514,9976 3313,3450440,79946,7301 3318,9049053,832144,6602 3321,4686355,142112,10076 3324,754690,611845,7760 3327,6361263,803849,7455 3332,6360725,735923,7308 3337,266322,300329,7670 3341,9945963,122919,9479 3346,5153324,437448,6899 3347,10517629,235663,5680 3351,5412727,798849,7254 3355,3982282,210206,9386 3360,1198804,901281,7997 3362,959706,818022,8829 3363,161406,5516,9823 3367,8918950,597155,9096 3372,8859070,422622,9971 3377,4815912,281362,7646 3382,8475741,862726,6859 3385,2023686,928981,6802 3388,8153265,796589,6873 3390,9333227,459464,9531 3393,7637888,87277,7844 3397,1029586,271026,10048 3401,9699283,426053,6621 3404,9984104,199132,6298 3409,2022795,785873,6380 3410,7855055,531269,7222 3412,1210072,370332,6631 3417,7470471,653161,6813 3418,8295446,32703,6454 3419,3992587,628439,7803 3420,6806026,889056,6366 3423,1716054,672776,9663 3428,8968130,869208,8552 3429,7324417,270451,6395 3432,5023837,852922,6978 3433,7358245,467114,7547 3434,8564845,402169,9662 3436,3381931,269966,7609 3441,4861818,269280,6550 3444,5684505,56775,10108 3447,8076862,845178,7390 3448,858979,284992,9381 3449,5925810,387428,10312 3454,9106636,154009,6235 3456,4746841,316913,9416 3458,6951924,859682,9285 3460,4042490,358981,5866 3462,2403232,100787,9068 3466,6399667,206911,6794 3467,7511190,491483,5964 3470,334808,937639,8440 3472,1547650,104902,9445 3476,1544010,117518,7404 3479,8241082,138462,7951 3483,2582692,878650,5812 3486,8727527,245649,5743 3488,4568305,651941,6782 3489,6737561,877068,6178 3491,4920925,731254,5913 3492,4296179,918340,9577 3497,3169889,379879,5783 3498,4888003,398944,7229 3501,4503115,509370,9026 3502,1653375,614853,7848 3503,1504091,13242,7240 3508,8519509,451240,7017 3512,4409665,98282,10233 3517,287225,354620,7325 3522,6312092,419397,7598 3526,9486493,874913,7486 3527,17884,842702,8376 3529,8934017,391824,5932 3534,8525319,516982,7757 3535,9759683,579285,8649 3539,5417335,869637,7941 3544,7887617,78305,9468 3546,9273715,870336,7282 3550,57681,682420,10659 3552,2409012,232771,7706 3556,5939448,786029,10391 3561,9095702,532593,9310 3564,8580594,101539,6768 3565,3153330,771104,5858 3569,5079773,304502,7816 3573,7149836,30872,7157 3578,1229589,135897,9374 3580,8905371,571804,5971 3581,9368220,869821,5837 3584,2495387,189308,7210 3585,9510563,794861,6944 3590,3040914,271126,8263 3595,5472907,547222,8419 3600,929224,476508,10233 3602,8368499,657901,6230 3603,5047839,62458,7648 3606,4741909,509414,6586 3609,538663,381515,8242 3611,7125817,861905,7612 3615,4740033,915125,8289 3617,1042190,230660,8279 3621,7393670,818323,6855 3624,5376633,603214,8895 3627,4768971,855119,8249 3632,8140991,499342,6134 3634,7356974,789609,9082 3635,1210282,365298,9513 3640,1349517,860087,10684 3643,2663982,901153,7088 3648,840703,113598,8587 3651,1385871,590304,6948 3655,7980035,95768,9948 3659,8277625,481325,10616 3660,1413699,320610,10601 3661,5598721,552394,9417 3662,10638448,564751,5796 3666,1230707,823469,8446 3667,5686984,360936,10298 3668,4990655,841435,8224 3669,9221545,337563,10489 3670,4473862,22264,7424 3672,9639931,923884,8365 3675,10224857,910663,5802 3678,6527409,193294,6581 3680,5491949,907282,7706 3682,6247731,84865,5950 3685,5541313,825071,5747 3690,10587434,240626,5645 3694,5434710,729910,6110 3695,9727663,15839,7840 3696,9877523,786541,5923 3697,4375027,687300,9628 3702,8733075,401462,6724 3706,7490643,103136,9774 3711,5250115,679556,9944 3713,10277026,644254,5816 3714,4011547,95909,10545 3716,172965,175425,8266 3721,7091620,179773,6436 3722,7304472,927952,8276 3725,926275,498952,7017 3730,975901,271828,10465 3732,636438,24164,7983 3737,2925912,315638,9134 3738,1384359,869471,8329 3742,1995501,704660,8466 3745,7134138,50232,9512 3747,7010981,370314,9159 3752,2550227,595519,6938 3755,5115786,691039,10512 3758,7620364,808779,9956 3761,5307323,220276,10662 3766,1385410,72109,8840 3771,1683993,5048,6219 3775,1428370,24423,9763 3778,2559088,15032,9455 3781,6923275,55657,6463 3786,2949988,168074,9965 3791,10500637,50169,7897 3792,5428390,441373,7003 3795,1313714,885118,10127 3798,1381198,895006,9765 3799,9681210,512899,10147 3800,6878514,897147,7817 3805,9352585,555905,6468 3806,10002973,267459,8475 3808,679736,715769,9246 3810,4248102,381271,7456 3813,4017366,651821,9949 3814,940332,762032,6310 3817,9091485,389609,8871 3822,6779420,389295,8442 3827,7388316,453473,5914 3831,355507,730539,6959 3836,2504991,457932,10021 3838,8109392,488378,6692 3840,5294765,595552,6378 3845,940074,497275,6349 3846,2926398,439711,10594 3850,4123550,207681,7339 3853,3557245,362583,8706 3858,8687044,163842,5780 3862,9933049,392009,10694 3865,5380160,698337,8716 3868,3967511,618640,7679 3872,7814949,60026,10220 3877,8152156,434984,8919 3880,7311522,560709,5932 3883,2305615,740965,9221 3888,10052267,608013,9573 3890,9905395,36354,5691 3894,6340235,186237,8282 3895,2540160,693565,7896 3897,4305898,479537,7905 3899,5817558,657494,6272 3904,10550969,367244,8055 3906,7345521,180310,8157 3908,6886312,657641,5923 3913,6236505,628653,10135 3916,10532283,574151,10022 3920,9789793,597140,8170 3924,8463093,61449,8632 3927,10312393,917117,7864 3929,1738414,572725,8012 3932,6812053,724854,6538 3935,8957132,788013,7502 3940,4063033,217554,10511 3942,207557,596823,6153 3944,10652491,688308,7912 3948,6783030,276217,7470 3951,4318244,95616,9690 3954,9081488,190389,7416 3957,4308310,930579,8070 3960,1281871,28873,8963 3961,9600962,259351,10102 3966,8776104,747280,6408 3968,5746264,169537,10011 3972,7632544,614675,8063 3975,3421046,482828,6855 3976,7224687,938120,8880 3981,1569013,319049,9392 3983,596796,454560,6656 3984,2515348,349732,7772 3985,10357307,154657,9943 3990,1466784,356491,9592 3994,5186435,889100,9481 3998,6780579,105016,7449 4001,1501804,298582,8145 4006,6067667,618001,5874 4010,7726115,352576,6646 4013,2519866,626329,10357 4018,3946801,722871,6879 4022,7819303,867120,7611 4026,756455,591325,5977 4028,339407,278873,10204 4029,9885774,187783,10634 4032,3155080,430290,6500 4033,3904413,424254,9907 4035,2762711,386710,8176 4038,1158909,358466,6703 4042,8208165,309992,6733 4047,7566446,702253,7925 4052,3243564,768158,9718 4057,2286994,3375,7491 4059,6812788,238041,9195 4063,10593846,421530,9204 4067,10520155,449028,7943 4070,2101696,430764,6590 4073,6334844,169444,9830 4078,7673476,902437,8043 4082,10316184,883823,7840 4084,2675613,412808,7369 4088,7853982,352098,7218 4090,4805354,650976,8369 4091,8734598,190058,7884 4096,681218,67485,7492 4098,3781747,230173,9546 4099,3988490,115995,8719 4104,3348446,806077,9687 4107,8122724,491388,7686 4112,651079,9673,8921 4113,7842556,465802,9772 4117,7173663,623631,7409 4121,5780437,379512,5993 4122,4997289,452785,7736 4126,5866982,342559,6601 4131,3795859,130769,7396 4134,6266215,892579,6802 4136,8297714,334644,7276 4138,3934278,686531,10034 4140,211132,929997,9346 4142,10031711,212686,8673 4147,2723565,742453,9325 4148,35296,146368,6012 4151,10095200,562381,7035 4154,9727442,11513,5946 4158,6155449,896926,8608 4161,1461960,553968,9876 4165,7148173,702009,7233 4166,6103885,517250,7715 4169,1495505,368674,8776 4172,5765112,246768,10166 4174,9078927,650283,5665 4178,1541445,137972,5873 4183,5006982,172156,8704 4188,6753327,156097,7732 4190,5919531,571447,10110 4192,4500683,32948,10533 4193,1638812,663877,6515 4197,4597326,20713,8768 4202,7445989,176611,7321 4203,3419167,296251,8154 4208,5163187,852228,10090 4213,10411270,707927,5813 4216,9503470,464884,7006 4220,4778567,603670,10396 4222,10073417,555930,7566 4223,2956226,389541,6902 4226,7633085,517974,7551 4227,9124810,15113,9718 4229,4804007,548040,7279 4231,5388585,88229,8904 4235,9152596,631249,6581 4240,10228094,649013,9927 4242,8135008,249121,8428 4245,8372760,115834,6616 4246,6460877,637970,5918 4247,7498164,406728,5772 4250,6905370,288546,9461 4255,7046064,523754,7704 4259,7868517,212525,10069 4260,4295320,511542,6588 4262,9130747,399337,8084 4267,6869621,174499,9429 4272,390360,233875,9248 4273,7762423,415525,7750 4278,8444628,64671,9886 4281,7636862,683083,7076 4283,6094289,325432,7329 4288,4310770,179933,10213 4289,9281131,274770,8997 4293,9578062,409414,7092 4294,7865827,287298,10633 4296,8718961,115855,10396 4297,695889,485045,8489 4299,9709860,60808,6649 4303,5328984,26081,8846 4306,154790,844731,9958 4309,1782385,356650,9973 4310,8484187,166126,8186 4314,9913349,576971,8694 4316,10541160,253195,7273 4321,1979003,765862,10396 4326,6648985,932313,7876 4330,2471931,842935,9358 4333,4773539,820945,8931 4334,1324353,625242,7382 4337,4743917,121298,6252 4340,5176598,53672,8273 4345,1913030,321819,8152 4348,9676701,824719,6803 4351,6921015,681178,8521 4355,5079745,287894,7253 4356,1740627,429413,10158 4358,5024214,484255,10677 4361,10492214,223347,9661 4363,3754090,933999,7279 4368,2948882,809360,10438 4370,10666687,205103,6092 4371,3498274,700265,9927 4372,3641226,234683,7880 4377,9546840,251305,8127 4378,6024572,215718,6095 4381,9958777,839493,8695 4384,1953063,669815,5881 4386,7436648,423214,6444 4387,4260544,643706,8773 4388,8465739,481924,7951 4392,9883188,712820,10358 4393,4549326,181455,9528 4394,3798168,26672,7839 4397,4630253,575008,8188 4400,1847453,790549,6717 4402,6681547,555562,9831 4405,8547958,747294,6012 4407,2394774,275585,9320 4411,5161239,879863,9239 4413,5240773,830602,7910 4417,8924871,431824,7356 4418,9155156,390096,6603 4422,3348253,770467,7549 4424,7720075,248884,9145 4428,4916063,291502,7717 4432,1708968,11532,6109 4433,9563575,341439,7158 4438,8093177,177997,5978 4442,9665063,278240,7513 4447,470726,676803,6053 4448,7059059,855725,10534 4452,1775668,476393,6803 4456,10326491,738028,6556 4459,5740669,663481,10253 4463,9574615,825935,8255 4467,1797888,192721,6670 4471,54565,793578,8569 4472,285778,522526,8886 4476,10543802,127737,6596 4479,5964906,208872,7425 4482,95190,324593,10105 4484,7092925,82602,6193 4486,6055733,400147,6383 4491,5745483,636684,9317 4493,4017831,188636,7152 4494,6226774,2017,6574 4499,2454419,528396,6661 4503,8298382,870272,8661 4505,4798170,901354,10495 4506,2450575,57602,6400 4510,7036085,193758,9215 4511,9492305,42482,9549 4514,6898293,431814,5877 4517,3348627,291518,8710 4522,1669822,600336,7537 4524,3495165,401487,6652 4526,41000,166155,9023 4530,8992736,254901,6692 4534,9072255,372917,7627 4536,6841001,926666,8709 4541,8019405,884843,8939 4545,9616150,115339,6404 4547,4586746,346445,7876 4552,7055137,9491,7927 4556,6788832,420729,6434 4557,3410965,351155,8195 4559,5862019,357838,5883 4564,4182398,35619,9035 4569,9616870,934486,6894 4571,5801600,49431,9792 4573,2196433,518883,6439 4578,470999,178492,8133 4581,10079938,219721,7351 4586,5408685,176777,6237 4589,3027617,390211,7983 4590,8896295,218066,8054 4591,714727,312676,10295 4592,4678971,820958,9081 4595,3864217,115051,9931 4598,3582372,681957,5974 4602,7514102,774355,6785 4607,7697471,565856,10376 4608,1097155,283585,9902 4610,7669743,164322,9879 4614,1166909,424764,10654 4619,9390892,529900,8306 4623,3895059,442684,9982 4624,4221928,581228,8456 4629,4562503,414798,10173 4633,3789958,286030,6612 4634,2181937,542856,6505 4635,6294336,938049,6904 4636,6977588,560980,7680 4639,9327995,921210,6023 4643,2100317,408121,7199 4645,7412641,557696,8678 4649,6673887,577438,9850 4652,10029193,691256,7832 4656,5495912,759891,6840 4657,7270664,20032,7161 4660,8710370,690022,6058 4662,10219111,160592,9468 4663,8824524,78758,9677 4664,3595111,545982,7130 4667,5112928,59936,10140 4669,4317266,348765,7915 4670,3012540,156060,7767 4671,7919119,490835,7563 4673,8459695,659160,10108 4675,2602733,402036,7770 4676,702903,792099,7857 4677,178670,331291,7998 4679,543708,797201,7327 4683,1497719,617203,7043 4687,1908123,521254,8270 4690,881320,630315,6054 4693,7822703,602198,8308 4697,2572164,28938,6708 4701,6014276,860228,6618 4703,1583526,64077,7176 4706,9078934,808202,7997 4707,8092701,668232,9834 4710,6086488,82252,8278 4711,1190590,22929,7444 4713,1310287,432067,8889 4718,8395847,598100,6300 4721,6466986,306088,6394 4726,2294170,330339,7803 4731,5528842,177905,9226 4732,8061146,256441,7263 4735,5342011,454058,9022 4739,5103652,95403,7414 4743,8489524,576938,7568 4744,2270235,458821,6135 4745,7157740,766354,5931 4748,2762356,544996,8779 4753,6490668,835725,7254 4754,2782855,653304,10606 4755,2707914,346478,8018 4758,664643,197248,10276 4763,2895550,80759,5988 4765,9144837,501831,7072 4770,6250132,667303,7122 4772,2303574,786320,7002 4777,10380980,463826,10410 4782,1574890,155508,9663 4784,2234024,286200,5936 4787,8439729,30203,7604 4792,832832,370166,8453 4797,3621382,181625,9331 4800,4502672,141014,10652 4805,4642939,518683,7712 4810,9746903,883807,6358 4814,9980253,618661,8019 4815,1004598,745164,10060 4818,6684375,444934,8664 4819,10547433,268575,8628 4820,5840082,30686,7087 4823,10322044,444365,10682 4825,3024946,524559,8394 4826,1698428,812023,9631 4830,544385,157245,10468 4834,5516159,545469,7290 4837,3004480,131984,9499 4838,1920741,867259,8901 4842,567613,393105,8001 4845,10181416,871976,8810 4846,9795753,126767,7454 4850,111110,85754,9447 4852,2208501,679252,9956 4853,1850507,126922,6560 4856,4679645,534212,9487 4858,10380465,26945,9806 4860,4875962,206338,6891 4862,6740420,18017,9051 4865,5535819,537416,7370 4867,7337434,1859,8876 4869,7832886,918909,10486 4871,9650027,40805,8153 4875,3458238,274393,6652 4877,8121820,25818,10383 4881,309384,213456,9070 4885,7955547,332503,5807 4888,4474573,367204,6944 4891,740574,161524,6922 4894,119521,43967,9467 4899,3635227,683855,8216 4904,3135628,226726,5898 4905,8865547,532057,7368 4908,5848536,2042,7851 4911,9695945,886904,5935 4916,5033025,802224,10429 4918,1471524,281474,6280 4923,6905831,718271,9937 4926,8736277,763047,10393 4930,3342374,569117,6134 4933,10638727,303464,7392 4934,7255534,277971,5868 4936,3821535,554884,10468 4937,923889,606479,8538 4942,1156563,260578,8098 4947,4594664,880663,10462 4950,3598773,238319,5656 4954,6145640,763506,7233 4957,9922476,335877,10540 4960,9733331,676005,5622 4963,8259257,544061,8520 4968,978780,253002,7458 4969,8046271,74639,7243 4972,393853,538342,10540 4977,10219891,319259,9034 4978,269102,546671,9569 4983,8783071,902275,6812 4987,2790456,851684,9614 4988,7319712,202361,8657 4992,722105,819900,6812 4995,2381109,846694,7182 4997,4092869,726142,7193 5002,7533351,84009,10616 5006,5167235,674461,7106 5010,10609293,289645,7137 5012,9136034,682806,7156 5013,8907932,54900,7623 5014,2507323,887516,5676 5019,6271859,796393,9905 5021,103542,548955,8454 5024,5573501,445317,8580 5027,1206469,3100,7791 5031,714419,614478,6522 5036,4359232,314081,5703 5040,6406530,762440,5647 5041,96891,76819,9778 5046,1894575,552654,6514 5050,2589374,100324,7674 5051,10519795,153518,6378 5055,7746223,610582,9342 5057,3706775,692154,8707 5059,8116737,444503,9097 5060,3973452,405568,6948 5061,6440900,348408,10657 5066,365872,284098,8058 5068,4425942,446625,8747 5069,8177039,271384,7138 5073,8415717,625364,9427 5078,3632822,922018,8099 5082,2378029,16362,9029 5084,8840850,468119,9787 5088,8143851,822072,8690 5090,10652032,364053,9308 5093,9156699,480568,6967 5098,877120,555836,6628 5100,6630878,725570,10619 5103,6760723,640790,6504 5106,655844,88881,7756 5111,10499407,615085,7992 5112,3309578,664062,8628 5116,10028564,157152,10548 5118,407661,120354,5727 5119,7664029,766933,9545 5120,7150888,197249,7144 5125,8010256,299597,7071 5126,4690526,800160,7309 5130,6892696,13802,5992 5131,2866960,233971,5684 5132,8128621,592080,7347 5135,3037861,77221,6075 5139,7229312,196390,7564 5143,7859368,433925,5869 5146,10061576,41979,9979 5151,1065660,477340,6855 5152,980387,678283,8810 5154,1793294,446435,6967 5156,1347100,577781,6439 5160,589579,169402,8178 5165,269083,768411,10160 5170,474134,335199,7198 5174,9254020,372057,7189 5179,7543058,877596,7074 5184,5616723,861414,7532 5187,8346724,894628,7815 5188,5949944,930256,8738 5192,5063079,864007,8830 5196,2264140,271278,7690 5199,9090707,549581,7232 5204,8077864,468602,8148 5205,8594838,463580,6169 5209,6088559,197912,6748 5214,811613,763728,7522 5216,386474,769303,7516 5220,5727576,55633,6490 5225,3558209,710812,6846 5226,7320116,646568,6860 5229,3162185,172059,7190 5233,9301919,747226,8326 5235,7813580,555222,9658 5239,6627114,803914,6869 5242,1438482,637491,8778 5243,4470797,610813,5981 5245,10524014,233915,7099 5249,7672899,300160,10573 5252,3207835,719169,8893 5253,73283,827912,6754 5256,2382678,934695,6287 5261,5030823,634489,8750 5263,3229470,409198,6850 5264,5745526,53628,10627 5265,3175880,819192,7433 5268,705739,711374,7668 5272,4722470,578171,8798 5277,514833,274906,6494 5280,412451,347379,10270 5284,9426901,590828,9010 5287,3173461,44607,7834 5289,1746095,755553,9454 5290,1442142,308662,6556 5295,933212,443575,5979 5296,5213534,111572,6432 5297,112509,208349,6135 5301,10290403,564064,7675 5302,6514957,542961,10412 5306,7447917,39802,6083 5308,3311493,514907,6288 5311,5766922,130284,9037 5315,7078460,187670,9380 5316,4700192,245835,9369 5318,7273061,891151,10573 5320,2227963,90146,6147 5325,798844,833518,6014 5328,1836032,140160,6450 5330,8404853,875262,5735 5331,3325817,418087,7956 5332,5896922,138708,7427 5337,6333410,632391,6352 5339,8349924,874333,6407 5343,9371084,757799,6745 5344,1231416,635216,5731 5346,4610035,638023,7353 5350,5909395,678929,7490 5351,4591672,271438,8925 5354,1062399,625734,8642 5358,3450674,257478,8288 5359,3283056,846414,6776 5363,8229412,159893,10117 5368,9945519,758957,7546 5370,9720246,367529,7695 5371,7815482,775450,7474 5375,3935978,794016,6314 5378,9846327,108700,9012 5382,6035296,519355,5766 5386,917051,595306,5729 5389,10257956,517208,10079 5394,2311634,19874,7848 5398,1657554,524738,9670 5399,7526298,218119,9613 5402,7124375,175343,10143 5405,6195591,885238,8691 5408,4105579,815751,7773 5409,9878815,37661,10546 5413,2777619,303914,10689 5416,2960341,206597,6548 5417,5434910,903247,9479 5419,5132428,829808,6137 5422,37239,167486,7847 5424,3276446,817240,10077 5426,2286455,541437,7237 5428,1490580,421793,9115 5430,10441940,927707,10371 5435,7876665,718214,5908 5440,885654,683339,6444 5441,338869,871229,8316 5445,8115464,259645,7171 5448,3454949,162932,8909 5452,359849,233095,6934 5455,795360,92199,7331 5459,6983845,876005,8546 5460,9279682,331453,6211 5461,28094,497930,10593 5464,6456790,238840,6664 5469,2906498,34926,6946 5473,4892729,250668,10428 5476,7882635,141733,9385 5481,10000729,147788,9918 5484,3530616,841929,10066 5489,10196235,762486,7386 5492,1984279,265596,9128 5494,1631995,589485,7253 5499,9622395,297705,9282 5502,9049548,528977,9398 5503,8274825,28496,9967 5504,9020330,651439,9199 5506,8037907,895797,10258 5511,9401950,623396,7887 5513,1816029,175963,10089 5516,3047383,393436,6123 5519,5239404,543987,8665 5521,4841536,884468,9439 5524,6018501,437926,8677 5529,1219390,541754,8738 5531,4989165,122403,6942 5536,2039871,269521,10600 5540,3516498,922278,7610 5541,3632860,828164,7759 5542,2840424,549047,8153 5543,10576285,154736,9775 5546,9191099,886144,9559 5548,7312012,392215,7817 5551,6300674,386626,7415 5552,8292353,733532,8318 5553,9496713,763657,8429 5556,6413360,181871,5982 5557,7467972,7185,8650 5561,5577443,624855,7793 5564,9400733,842028,8648 5565,3236780,932659,5878 5566,4650998,125711,7252 5568,4976778,431406,9328 5572,6169362,684004,10213 5576,104684,580950,8779 5580,2398406,777923,6866 5584,5233890,862235,8075 5586,4119410,702734,6363 5590,961785,825073,5699 5595,10662425,728680,7696 5596,8984594,389332,8665 5597,10113231,308247,6167 5600,5063681,371227,8261 5601,2432873,603776,8964 5604,8318084,63643,6735 5608,7517574,895418,6446 5610,6910557,231795,8913 5611,9746000,291818,9822 5616,130723,866953,6652 5620,4556394,869710,6634 5621,7029552,686746,5950 5622,6384186,883933,6525 5626,4584795,567198,8336 5630,870121,800689,9151 5635,10400766,402146,8017 5639,226072,786112,7035 5640,4129940,231583,9866 5641,2840804,451891,6379 5643,754039,67491,10232 5646,1070059,236572,10237 5650,5255457,93426,9476 5655,4406859,834955,10376 5660,9457408,564386,10632 5662,4526952,453898,9627 5664,10597648,77442,6069 5667,2089369,111496,5922 5670,5111259,551826,6212 5672,4883240,912846,7719 5675,2496580,404694,7003 5677,4232979,740244,9191 5678,3685524,348511,10154 5679,2891922,444768,7903 5680,9419771,139844,5740 5684,3371234,562437,7479 5686,6577070,553167,6496 5689,9394998,627822,9602 5694,6804449,374115,7471 5697,8519249,654441,9967 5700,2344068,37284,7953 5701,8710486,515402,9065 5706,7969406,112413,9479 5711,3512293,682063,9162 5716,8887871,832716,10323 5720,10122927,656499,9836 5722,8244879,707540,8479 5726,724222,647,5658 5730,5713688,183592,8913 5735,3441218,422033,7848 5740,3737061,378173,7093 5744,2839598,502989,6909 5746,9438585,111116,7830 5749,4157951,188695,6044 5754,3913439,128063,7851 5757,5655260,254323,5786 5762,6633325,290121,8642 5765,2024994,141895,9683 5766,2048368,353778,8985 5771,10355836,875869,6353 5775,8913810,747254,7633 5779,7056202,801459,8096 5781,3718358,245389,8009 5782,8051197,885211,6171 5784,2829080,79936,8739 5788,10400648,342006,7281 5789,5910381,77048,8829 5792,1590228,169535,8085 5794,2293123,860816,9600 5798,8761853,736637,9544 5801,517590,432871,6173 5804,6895357,431830,10273 5809,7993530,736972,10578 5812,8567655,200695,5700 5817,3726031,894527,6410 5818,5966023,116621,9391 5819,7232818,928536,8661 5821,6387387,191021,5742 5825,4329846,566722,7654 5830,1011366,887906,8077 5832,50800,343796,7659 5835,5531128,56825,9923 5839,10121218,856439,7540 5844,8520035,482452,10220 5846,1119415,187022,5617 5849,9760704,473878,8939 5853,3743863,207301,10069 5857,5574680,280920,8788 5861,5716874,479524,9447 5863,8384141,522484,9411 5864,6772694,666622,9411 5865,9353018,657198,5630 5870,659356,31974,10076 5873,5201518,743713,8281 5875,2273816,934202,7153 5878,9006035,670600,6579 5879,1049250,200765,7232 5883,8634387,798404,6920 5885,6680949,656960,8126 5887,3498879,903702,7790 5889,5462455,934457,10603 5894,7484250,819262,7465 5899,124979,831042,8758 5900,6634021,871390,8899 5901,821099,294851,8737 5904,1205491,183608,8857 5909,38499,355657,7453 5913,913106,566856,8900 5915,9773107,859842,8562 5917,1897099,29074,5658 5918,4762749,654010,6731 5921,8664132,862423,10158 5924,7486682,542682,8738 5929,6149131,784635,9709 5934,6419014,645028,9312 5936,7808762,511418,8061 5940,1327384,676387,9056 5944,1258591,498666,7508 5945,5761076,435300,9648 5949,10206259,397276,9109 5952,7094787,363386,9578 5957,2400850,921527,10688 5962,3593692,732601,8946 5964,10016310,415643,8723 5965,5196358,811386,9857 5967,2456005,619348,9897 5972,9283129,350370,6862 5977,1011063,8065,9572 5982,10116851,24468,9964 5986,6510936,577023,7138 5988,1929898,775218,7725 5991,1929498,875373,10242 5993,6927203,651329,6471 5995,2206324,60904,10426 5996,196462,333498,6381 6000,5569557,472008,7669 6005,992581,362875,9419 6008,8242271,118780,8338 6013,3096732,208047,8278 6015,1016270,441889,5905 6020,8322902,151342,7756 6024,1984248,188283,5906 6025,8135863,836879,6453 6026,9037873,374334,6834 6029,5794499,129639,9752 6033,5688401,864138,6781 6034,8950846,441561,9495 6038,9665192,894965,7159 6043,8053523,543742,7601 6046,9584127,658298,10156 6051,4884783,201985,9167 6053,8299014,325295,6740 6055,9666185,792732,6437 6060,351000,682928,7282 6063,8793929,763729,5855 6065,8789802,251508,9371 6066,4356365,230853,6786 6067,8256515,98028,10436 6070,2497349,106558,10626 6071,5393184,666562,6144 6075,9409084,152081,10204 6080,5688560,312059,8429 6082,2427413,918511,10560 6087,9287689,455974,10299 6092,4375382,349432,9324 6097,4502466,722479,6469 6099,3369268,651333,7598 6101,229908,297983,7258 6102,4049216,43036,6119 6103,6110890,853862,7255 6105,2825758,531923,6733 6109,10305198,450144,6336 6114,2973259,481358,8418 6119,6220974,29757,10042 6121,7851661,252569,7549 6122,8698706,482570,8008 6126,5445969,475058,7353 6128,799213,110631,7621 6131,8294223,7021,7877 6134,9627445,820099,9719 6138,1208231,306395,8246 6139,5871207,769474,7292 6142,5976781,453009,9229 6144,7897238,439247,9868 6145,7051987,765591,10331 6146,6435040,688876,8011 6151,2796969,156281,10316 6154,5542525,661421,8581 6155,4665813,68350,7783 6158,8753271,354151,10638 6161,9648506,719518,8923 6164,4238807,643485,7955 6168,1529452,217034,5902 6173,6321157,816976,10681 6174,2880706,361667,9470 6179,9922357,453009,8905 6180,10634641,567945,6927 6182,7756755,12251,10662 6185,6148582,454260,5626 6190,7145597,602285,10301 6195,508260,729709,8878 6196,8194846,802350,6105 6197,10300411,226552,9528 6198,7017927,633615,6876 6202,10286918,399338,10525 6206,9947533,5183,9638 6211,6205197,305407,8749 6214,2629596,835959,8745 6218,9375873,766141,9302 6223,6565171,80191,7909 6226,6714107,545965,9257 6228,5387884,741530,7160 6232,8674701,885966,9016 6236,7794746,77577,5704 6240,2297983,712802,5730 6243,6050980,688469,6650 6244,4646401,839576,10437 6246,8052064,841735,9740 6247,3491041,71166,9719 6250,4419005,917408,10489 6251,5350898,626816,7923 6252,7374633,500604,9958 6254,4929047,308267,9195 6258,1279349,231020,5888 6259,9388969,410437,9356 6264,9720739,238343,6372 6266,1887260,665859,10680 6269,3725678,97694,7966 6270,6992782,724610,5998 6272,2133994,164466,6508 6275,2089507,758336,5674 6277,2997272,403050,8437 6280,4293505,44876,9057 6282,2075435,744082,8342 6285,1838118,477886,10061 6287,4075201,73746,8139 6292,132955,596973,6508 6293,7836129,459304,6472 6295,8294077,373651,7345 6297,6822714,150230,8773 6299,6685693,209963,8735 6302,2822706,709139,9292 6305,2966955,400564,6886 6308,1810023,627610,10405 6309,227447,402046,10006 6310,5563120,42614,5991 6314,867657,918695,8709 6315,875127,802648,6519 6318,7623440,659277,10000 6321,2360629,398652,6048 6325,2437149,62235,6447 6329,8675085,525989,10089 6333,3790221,396841,6657 6335,2728984,529158,8386 6336,6695187,190257,10262 6341,8367021,504724,9839 6344,7337096,378362,7089 6349,1401867,31731,9350 6354,3542336,732775,7140 6357,9256966,753969,6328 6361,9645610,479747,6406 6365,5842332,783597,6158 6369,9922314,476014,5639 6370,4082773,933183,7099 6372,9945336,579972,6663 6375,2714745,678081,8653 6380,9398465,370733,10443 6383,7839074,480921,9748 6384,2173399,172155,6002 6388,5627823,747340,9058 6392,6885517,711579,5979 6396,512754,936731,8302 6400,7806395,868656,6852 6401,7946530,236222,9165 6404,8131705,845296,6898 6409,1791759,787994,10632 6410,7044381,468249,8540 6414,7025663,240003,7455 6417,1535515,432763,7903 6422,253700,392202,7874 6425,7986921,628219,8096 6427,420444,172646,8286 6432,8486446,586134,8916 6437,4120073,348164,6466 6438,10252938,519932,7302 6442,8097032,406100,8158 6445,6747283,534332,8847 6448,6739025,442626,8380 6453,6575276,710349,6819 6455,9913903,624296,9826 6456,2402872,88296,6783 6458,6861297,725941,8223 6463,9195874,53855,8994 6464,2845294,552108,7493 6467,9917426,710182,9473 6468,2453014,57215,8542 6471,292738,223369,6255 6476,6109134,276729,9909 6479,4243807,498375,10473 6484,557427,650607,6033 6487,3664862,457751,6618 6490,7191419,628922,6385 6495,1286248,779470,7702 6496,6973456,445805,6216 6499,4471767,444149,7525 6504,4153355,272743,7910 6508,6800700,117924,6436 6513,1817336,751826,7307 6515,3561752,576146,8201 6516,6073420,845414,8984 6521,9193026,87402,10535 6523,610685,637017,7641 6528,9388582,57888,8193 6533,3572518,884548,6893 6535,7851825,318847,6728 6538,6537956,103380,6878 6539,10196127,85444,10021 6541,6998690,701854,7260 6545,8903794,776842,7013 6547,6293755,186296,7582 6550,7575189,594548,7750 6553,3481073,394282,6952 6558,3586866,471205,8736 6559,2277383,151709,9531 6562,867036,543951,5964 6567,3095887,424980,9812 6570,801706,608357,8284 6575,7265478,702295,10671 6578,7000505,758455,5710 6582,2485259,438573,5968 6583,3114929,682614,9144 6584,7555284,230428,6606 6585,6802147,772464,10557 6588,6089034,713083,5847 6592,10669362,136796,8803 6595,6857090,646137,7577 6596,8901464,319378,9977 6600,10137132,101858,7984 6603,9187592,476545,7831 6608,10080827,680682,6387 6612,9881195,774140,9692 6617,6426266,1889,10627 6622,8145270,559262,6383 6627,9657802,578623,9034 6629,2793606,498183,7158 6634,1278423,191677,8836 6636,6553445,113918,8963 6640,178920,659314,8815 6644,8859250,115482,7972 6648,4981014,436292,9895 6651,1534584,90419,7939 6656,4308430,62116,7794 6659,1574825,206911,9578 6660,5311181,521502,10639 6665,1090416,290266,9971 6668,3715973,577043,9309 6672,731683,222818,9622 6673,2142527,431232,6654 6676,5657932,817186,6723 6681,4866789,502987,7263 6683,10323218,224175,8480 6688,3378651,743478,8095 6692,5292968,3896,8914 6695,6185471,50549,8267 6696,1457215,418711,10302 6700,9949964,721214,10254 6705,2828947,647534,10415 6709,3088062,300406,10129 6711,7822588,373117,6959 6715,8518188,669326,8362 6717,5595847,697838,6211 6718,2407525,339963,6335 6722,7703162,922427,8106 6727,1799343,553105,6985 6732,615798,28003,9467 6736,4420535,253856,8595 6741,6883048,809715,7393 6743,1796782,15780,9613 6747,7104400,819044,9702 6748,5553514,317439,10375 6752,2269391,212766,6283 6754,895258,207139,7568 6758,8074056,699080,9904 6763,5700748,491716,8247 6765,840630,253242,6330 6766,7326475,602535,9904 6769,1234503,795933,8299 6770,7851756,423854,7829 6771,4280636,248854,10685 6774,2274463,892159,9037 6775,2921537,481879,6467 6780,7816110,541650,9299 6782,9762318,102496,9952 6783,6700829,528897,8706 6785,3672564,845220,10355 6786,572558,12705,6625 6787,2527695,758717,9674 6792,6968204,402990,5763 6793,1375304,834608,10686 6796,360465,44199,5710 6799,8459209,562718,8330 6803,2430730,903188,9982 6805,7903881,119868,7319 6810,491631,233244,6734 6811,2629434,893742,5814 6814,589801,458880,9290 6818,1235438,102108,7146 6822,8757984,575072,9842 6823,2288263,324644,10189 6827,9992289,311377,10499 6831,581566,703999,10657 6835,8711621,612133,8582 6839,8005484,746154,7430 6840,10634999,313604,10050 6843,10606711,895796,10158 6848,3484056,912945,9360 6850,9257083,432462,6035 6855,8244093,507706,8346 6858,2500930,425287,8420 6859,8046088,87540,6543 6863,10328928,479353,5652 6865,10670987,636808,7979 6867,9893461,464033,10243 6871,9032491,727574,7782 6876,7743975,909295,10594 6879,4077462,554120,9332 6880,6977979,43758,10161 6883,4597304,180127,6486 6885,7590645,809682,7780 6887,5164216,503377,9296 6891,5487789,172015,8189 6895,1608184,156796,9962 6897,887916,288835,5946 6902,4712397,110867,6973 6905,3237959,717812,9274 6910,10031699,41662,7801 6913,7423960,859019,6761 6915,2911669,254145,8545 6918,4480656,518398,5898 6923,2369928,700061,8744 6927,9292918,379194,10002 6928,1908766,616237,10215 6930,7968958,318121,10314 6933,5142715,862976,10078 6937,568410,595773,8829 6941,2990289,575964,9073 6946,1694704,732852,9859 6949,6871461,445455,7481 6954,407944,733745,10388 6957,8632911,179271,6109 6961,2205422,430644,8090 6963,9344299,645994,6137 6964,7001595,921036,7367 6968,9638428,876849,8011 6969,8890947,458431,7198 6972,3604600,218331,8939 6977,3732569,619648,7132 6979,4717671,859239,9418 6980,8271002,591899,7973 6984,2896942,387307,10042 6986,5102478,385679,10049 6989,8734954,366403,7863 6993,3028778,205122,10594 6998,3587874,59037,7628 7001,2157749,501878,6595 7005,2346332,330328,8602 7010,6893426,401836,7102 7013,182337,313103,9856 7015,932845,272415,9661 7016,8584508,444739,8945 7019,4122291,167944,9151 7022,5793134,540308,10504 7025,1754569,482517,8406 7026,4343733,788339,9085 7028,7051641,136495,10316 7032,2567951,585420,8182 7035,6263879,157145,7351 7040,9261028,869924,7354 7045,1159941,872499,6839 7046,987198,36720,7631 7050,1889700,493232,7009 7051,8263207,32538,7652 7055,2557127,215450,7160 7060,3363490,627736,7613 7064,9256118,298558,6163 7068,8988092,847466,8662 7073,3239058,867059,7221 7075,5874532,242796,7007 7077,6517393,365559,5652 7079,9909170,148511,8506 7080,9163521,33321,10032 7084,3554344,666647,8116 7089,8370516,836562,9330 7091,491220,385786,8520 7096,8251168,476431,7555 7100,3815963,171707,7631 7101,9947884,900158,8942 7102,5749106,344973,7432 7103,295611,55915,9107 7104,8851376,342830,6987 7109,8440351,435377,5927 7114,5797128,336172,8117 7119,9520349,400891,9119 7121,8585273,81835,8358 7124,5157672,66901,9113 7126,6486118,481590,7497 7131,3579648,608143,9307 7136,7056765,306790,7301 7138,5666981,447085,8608 7142,10353829,465269,9204 7146,10072169,461021,7804 7149,9928556,301314,9482 7151,8049200,803857,9981 7153,8813266,741452,7095 7157,8358904,321098,7372 7162,2932815,258248,7266 7163,4041370,481450,8953 7166,1815300,677571,6358 7169,3979106,352428,9130 7174,8538927,511494,9819 7177,2803000,67075,5923 7178,938319,546394,7711 7183,1360225,45380,8287 7188,4466008,680760,10164 7192,6686988,324001,8174 7197,6409954,303180,5702 7200,5074815,142919,6125 7204,8081522,447001,7254 7209,5463837,141539,9601 7213,5482674,879305,7713 7215,10615499,19484,6328 7219,1345347,318584,9507 7220,10522979,392895,9676 7221,7118851,773511,10273 7223,4999086,595730,9812 7227,6246012,204246,8067 7232,2472979,346561,6404 7236,2820351,593424,5617 7238,9713148,663508,6584 7241,5182367,419376,6210 7242,7037840,61677,7704 7243,9817582,874003,9968 7245,9833490,694881,5729 7246,1076590,632550,7051 7250,4306686,835314,9343 7255,9185972,493969,8974 7258,6290460,266774,8694 7263,4611554,22381,7130 7268,689848,684646,5758 7270,5863080,458348,8571 7271,8144948,362476,10333 7274,10052745,839790,9399 7278,6770239,151866,6286 7282,6913018,900851,6987 7287,4784626,359018,9723 7291,3991684,133465,5925 7292,6074326,869601,8848 7293,439413,507503,6860 7298,9299795,534468,7694 7301,3920210,127036,10080 7304,2310780,674356,8184 7306,5605948,151489,9226 7309,6906191,398538,7372 7313,6304035,527433,6801 7316,5722272,502042,8480 7318,498587,69357,8965 7319,8292921,363514,6389 7321,4768245,304597,8064 7325,1216840,369159,7347 7329,8129342,330900,9732 7331,10440201,179894,10477 7333,8752738,524884,7661 7337,3537621,505873,5909 7342,6718745,800728,7006 7344,6246615,423269,9760 7347,2548729,326753,10523 7348,1914123,129704,9668 7351,5372630,517500,8036 7356,829955,17557,9784 7357,5786956,475132,7674 7360,6222345,464485,7998 7364,6788098,562800,9570 7367,8650594,879417,6309 7370,8146895,23064,8301 7375,9760309,927288,7345 7378,8385133,444993,5915 7380,8851620,97493,7041 7384,4844707,774843,10456 7389,7453767,794546,9213 7393,3475232,163669,8868 7395,4334109,39994,10255 7399,9027420,517076,6600 7404,2162722,854066,5617 7407,1455513,706688,7058 7408,9011709,67750,7811 7412,6057481,314998,10154 7415,10119749,154270,5722 7420,4627057,623313,7811 7425,5305194,703137,10209 7426,7959097,272348,9547 7430,9352247,839576,9875 7435,514135,606379,8156 7438,6174700,109599,10336 7441,2819230,140236,7152 7443,8713717,163528,8957 7448,7485408,484886,9449 7449,4096531,600998,6232 7453,6356800,132026,6582 7455,9773472,366188,8699 7456,10424201,546973,10124 7459,6445592,403856,6521 7464,4683168,40996,8807 7467,7112096,688737,7654 7468,4785376,269781,9519 7473,9296125,243281,6464 7476,867994,607817,9825 7481,3134033,477780,5981 7485,5035656,645501,8988 7487,3969235,742074,9118 7491,6159162,67719,8274 7494,1633321,782567,9984 7497,1143766,849882,9790 7502,9682581,729469,9300 7506,3064329,170257,8727 7509,3512201,377730,8331 7513,7485308,463286,8496 7516,10620869,28115,10003 7521,9750892,448754,10150 7525,4095632,427567,7720 7527,1508514,868019,7466 7532,1871147,405188,9394 7533,7638692,617245,7905 7535,6556050,145104,6574 7540,10282557,12256,5975 7545,7578807,766054,10471 7548,3946009,534885,5701 7550,4619248,118514,7151 7554,8622365,612467,9626 7555,4927288,131665,6358 7560,9292472,776076,7926 7562,3958465,119506,8287 7567,955315,779929,5682 7572,7685141,170832,10135 7573,7589959,228103,9158 7576,9006535,831957,7084 7579,10078805,834049,6276 7582,1698783,192962,5893 7584,1291036,936842,5691 7586,5256307,623292,9450 7590,8013385,96036,7768 7595,2198698,132550,7303 7596,8452093,305416,9198 7600,1258427,224045,8571 7602,3401507,190139,8018 7607,6524,778384,7071 7611,1085737,61259,6161 7613,1267958,455155,6590 7616,5975675,821138,10256 7620,7288804,472683,9452 7623,5923938,422088,10488 7626,595846,843098,7062 7630,1361206,337029,6283 7635,8078689,392059,7531 7636,3876740,757071,7118 7641,9619468,440921,9064 7643,1930865,229218,7648 7645,7425948,14577,7451 7648,3508213,167639,8890 7651,1386929,387629,7575 7656,9789236,360570,6579 7658,5133660,697758,9004 7660,10234353,552324,9372 7662,5871222,900743,6262 7664,8597480,240827,10476 7665,2002633,120591,8351 7668,10280507,735794,9862 7669,2315240,471145,8993 7673,10400144,169079,9610 7674,3954168,107357,8974 7676,7679919,41837,7631 7681,1770472,273980,7369 7686,6313780,859581,5944 7689,931685,2298,6668 7691,6128969,360597,10291 7696,2750272,220948,9190 7697,3784140,902728,8887 7701,7736738,274954,9020 7703,4674645,653051,6765 7704,8715269,334875,7760 7707,7375458,885737,8065 7712,5501133,716400,5961 7715,1390598,331565,6806 7718,9850481,481798,9796 7721,5111731,677987,7049 7723,10495997,391842,6593 7726,1274444,382792,9552 7728,4628104,198537,9696 7729,3104848,879695,8754 7732,2644299,764340,7876 7734,4523111,178637,7109 7739,7184372,879262,10536 7741,10181701,118681,7746 7745,288749,738749,8828 7748,10200661,530278,10193 7753,8460848,207888,7184 7754,10654508,142163,7847 7755,2668141,144311,7299 7760,3203232,342279,9226 7763,3681982,66585,6130 7768,3655392,522076,7434 7773,1130344,586523,8276 7776,5557694,181815,5955 7778,6656599,814189,10219 7783,6545839,555161,9143 7788,7239668,671356,7181 7789,9851091,160413,5626 7792,7794585,324699,7786 7795,3581505,918098,7974 7796,3525064,743908,6760 7800,10062897,579997,7349 7803,5338873,642916,5792 7807,9285102,879811,10394 7811,1012368,465201,8832 7814,4505246,466628,8467 7818,6665172,280441,6554 7821,2161162,180878,7119 7822,9903580,802128,8472 7827,4288639,371398,6296 7832,7370431,871890,9366 7834,7517320,606958,8543 7839,8771053,636327,6249 7840,5114296,741553,10044 7842,10004708,98378,9448 7847,8761014,263213,9866 7852,7695367,893346,5794 7857,8915057,882956,9744 7860,9816471,725145,6289 7862,1054216,805508,5966 7865,6013618,411141,9744 7870,3633952,128257,6074 7873,9811801,313250,6996 7878,2382418,663967,10202 7879,4285741,874296,10069 7882,5906839,324301,6239 7883,547848,607147,9905 7887,1762979,423190,9507 7891,1695089,190335,9705 7892,10459224,866553,7222 7895,3744916,451353,6001 7899,10301678,337711,9625 7902,5094788,128807,8654 7904,1763551,920580,10050 7908,507068,931798,7394 7909,1479704,469163,6711 7911,2736683,160206,6906 7914,6205452,937097,9008 7915,7112108,812541,10068 7916,6104357,381131,8178 7917,6799543,60098,9863 7918,791247,511538,9624 7922,1655876,724154,6062 7925,5332756,102667,7754 7928,8963066,226969,7095 7929,8548926,448760,10522 7932,5931632,265207,9892 7934,3752419,878819,8139 7935,9065235,387772,8698 7939,9236167,189230,9051 7944,7097534,563773,10497 7947,6550737,781937,7647 7948,4861470,916661,8447 7953,6283020,518161,8927 7954,3997997,333881,5758 7956,6279585,864004,7521 7958,6318295,740229,6827 7963,7641526,245410,9697 7968,3163488,714054,7072 7973,3285254,52817,7850 7975,5736798,585682,6512 7980,4097433,650596,9447 7985,1611215,609236,6462 7989,9984109,676698,7507 7992,1889469,200549,7608 7995,210151,301670,10266 7999,6871940,50075,7802 8000,337399,396222,10492 8001,6893237,842497,5749 8006,7106308,427079,8144 8011,9705332,465998,10186 8014,8932925,302316,7546 8019,2512016,625558,9268 8023,439507,536517,9582 8028,4980761,860768,10631 8033,936890,287199,6562 8037,1614064,626369,9817 8042,7756299,703690,10305 8044,399132,173867,9082 8046,7356066,204084,9003 8049,6055029,731759,7527 8053,2603851,816238,6997 8056,4133980,494665,8919 8058,1057456,852409,9760 8062,513172,589389,6618 8065,664593,96322,8240 8067,2541684,551346,9711 8068,5128017,226879,6803 8073,9398803,68357,6037 8077,5912011,705804,7482 8081,9413349,668059,9194 8083,7361629,846298,7093 8087,6030448,581295,8998 8089,4389137,290061,10219 8090,2940312,571660,8965 8091,6502886,934115,9416 8094,10447607,19236,5864 8098,7854342,590607,8722 8103,9726945,243629,6690 8104,6110397,181545,10643 8106,4680899,726784,10091 8109,7399732,671752,10496 8113,1623155,124778,8294 8116,8876454,482842,6135 8117,6534464,625704,10262 8122,9574222,712278,7860 8124,7366458,496094,7804 8127,4328799,392443,8112 8128,7172510,809063,7358 8133,4678045,854943,8698 8137,6925556,878662,10417 8138,2326879,161278,7925 8142,4599507,868013,9444 8146,6758172,557132,10069 8150,63842,895985,9344 8154,10296909,397094,9239 8158,2600674,56617,5664 8163,10366936,113206,10003 8166,7356630,675956,8042 8169,5889586,697667,6440 8173,10490292,196090,7880 8175,599402,453929,8526 8179,1467898,840051,9013 8181,719096,412539,10535 8184,7760838,299422,8445 8188,3108219,341694,10149 8193,713556,483773,8305 8196,969647,687645,6611 8197,792995,875548,9462 8199,9305270,127036,10685 8203,826769,904122,9115 8207,9138225,711135,9640 8212,10610411,110965,9267 8216,4844531,1590,10245 8218,7735995,757858,6593 8223,358587,616836,9024 8226,3044749,841343,6737 8231,2610831,22352,7467 8234,4943281,114514,8083 8237,5870726,830694,9838 8242,7554590,658967,8605 8244,10658382,918209,7076 8248,1145628,618430,6027 8251,1534110,46180,7818 8255,9472845,746805,9184 8258,1562041,202871,5807 8260,3230128,907617,8150 8261,2246857,885465,7996 8266,5354361,144857,10288 8267,599991,106727,5714 8269,9317796,232013,5804 8274,4803548,227711,7556 8278,6950563,937158,6941 8281,3261292,694354,8788 8286,8255851,435710,9537 8291,4296844,111790,8454 8295,4317387,264840,9796 8297,8689706,167665,6614 8301,6568785,517365,8895 8306,7722001,709921,9036 8308,1113479,205579,7659 8309,5429620,835214,7247 8310,3638844,530888,7741 8312,3407414,189648,8001 8315,1111281,233888,9456 8318,10295700,598598,7361 8323,2188026,831168,6803 8326,3119695,774473,9446 8330,10058278,140236,6870 8332,6886217,788759,6502 8334,194733,917947,9683 8337,6568567,509190,10680 8339,5591092,392584,6323 8340,9480423,63304,7217 8344,1567196,66272,9675 8348,2135987,483910,9181 8353,707451,321058,7266 8356,3613530,481549,6839 8358,6100422,731920,9824 8361,9054528,464514,7566 8363,4010875,371623,10453 8365,7932631,72196,9310 8367,4173698,826541,5673 8371,5669366,893388,6557 8373,1854646,27638,10080 8377,6891876,430513,6792 8381,8630800,515649,10359 8386,5033320,446085,7147 8387,1280584,689882,7516 8389,6119056,530572,6304 8391,6528555,391724,10410 8392,8208261,179758,9166 8393,683956,86956,10680 8398,178734,598702,9226 8399,3098142,144072,6617 8401,4951805,558626,8992 8404,2005169,166089,8809 8406,4153872,188415,9435 8409,8781930,575359,9014 8410,8936002,262210,9631 8411,1964312,744968,6391 8412,2359376,98134,7691 8413,6034463,404062,7806 8415,10141547,579107,8793 8420,4214826,249353,10514 8422,6714345,433623,6965 8423,4920172,836379,8198 8428,6124090,930580,8204 8430,5674840,492601,10314 8433,5862321,598334,8917 8438,3128769,433767,7462 8439,317342,896313,7913 8444,1074076,336942,8155 8447,10488002,422333,8305 8449,1017850,692126,9824 8451,8701503,398683,6289 8455,1831489,479677,10235 8458,3642367,851598,10594 8460,4087825,350925,10351 8462,5205943,263978,9632 8463,7052380,21035,7292 8468,3629173,432202,6093 8473,4572523,636375,10612 8476,6212639,713286,6413 8478,2678730,590235,7073 8483,10258263,355351,7941 8486,6219,721724,9443 8490,4649917,661665,8845 8493,4714890,369112,10185 8494,5350163,139292,8943 8496,328304,462076,9988 8498,2606500,237951,9072 8502,4384508,418485,9876 8503,4396062,203687,7180 8505,6653718,607732,7865 8508,10668982,25426,10041 8511,653097,742231,5845 8516,8258979,859394,10670 8520,443691,796093,7629 8524,2384128,236158,9655 8525,7634048,673313,6118 8528,7974187,114357,7152 8533,1153953,686218,6605 8534,9528242,475959,8014 8538,5518266,697736,9965 8543,7770958,904085,8491 8545,4217684,149085,6571 8549,6485653,932540,6217 8552,10488695,141492,9356 8555,486793,653245,7930 8560,2144407,616434,6091 8565,5750952,29589,8399 8568,5729128,227848,8745 8571,5673098,623659,10095 8575,4250885,428330,8205 8580,9443127,635165,9100 8581,6335274,909999,5783 8582,7869930,365191,5982 8585,178440,522571,7011 8590,8544485,712502,8173 8595,8236715,812528,7254 8599,10503896,347713,10383 8600,5614932,151222,8190 8604,9317801,430708,8144 8609,1985220,720465,8621 8612,948008,905663,8890 8615,10479707,803889,6291 8616,708027,447692,8648 8620,9424715,103386,9428 8623,5243952,185112,5717 8624,5246304,653239,6346 8626,9534782,61896,6564 8629,9955304,61643,10154 8631,5079211,103513,5938 8632,10114938,48631,7618 8634,7777729,741699,7336 8638,3430028,786567,8720 8639,7637542,129983,9402 8641,1520134,358253,8000 8645,5443427,329756,8367 8646,8165486,798732,7308 8648,8187219,422054,10235 8650,6879071,574621,6855 8653,8974040,111691,8501 8658,3009262,486881,6613 8659,3673999,511086,7557 8663,402548,138907,6840 8668,2885657,908806,7249 8673,953724,358309,5845 8676,8706364,49758,8175 8677,1897304,711490,10546 8679,7567470,143725,5659 8684,4358739,888237,5737 8687,9473481,779863,7398 8691,5076343,412464,6767 8693,7053055,834215,5969 8694,9297777,240249,7916 8698,5063199,78177,8082 8701,1391622,805613,7399 8706,4229034,398510,9733 8711,5741545,18629,6707 8713,3120822,811233,8841 8714,3141016,94381,8256 8717,4045128,852384,9505 8718,3424846,368661,8645 8719,1385435,357286,9841 8724,7049709,296217,9897 8728,6568379,192468,7533 8730,6516198,305184,8026 8733,9985752,506494,8352 8734,61554,85177,10596 8735,2753664,72734,8832 8739,9042669,292824,8327 8743,1719882,336241,10305 8744,9036778,872150,9295 8747,952270,5364,8023 8751,3085762,926181,8408 8753,252201,217596,8315 8755,2875167,230003,8191 8758,8881679,88091,9582 8759,3369158,713092,9656 8761,726978,891234,6652 8766,7038560,758280,7480 8771,9891980,708904,9993 8774,9412050,44963,6923 8778,9702382,925006,6142 8783,7966864,372914,9092 8787,10492610,745649,5799 8790,4169622,860198,10555 8792,3109898,489925,9036 8795,7650978,695271,8974 8800,6151017,94172,8583 8801,1962837,307612,9308 8805,6490661,903731,6326 8806,6886178,200623,10161 8809,1505174,6914,5710 8813,10299425,336737,9462 8816,7438843,743633,7581 8818,9056998,114602,8272 8820,10486584,740816,8722 8825,655972,687120,5911 8830,1887078,156742,8668 8833,4096279,806305,9455 8835,6113820,658196,7744 8836,8122504,139276,7121 8839,7086876,311908,7200 8844,7346641,866770,7050 8849,1604781,208977,6006 8854,3770575,113340,5818 8857,7196168,826079,7274 8861,1601147,673375,7870 8862,7497818,859171,9759 8863,10086641,890025,8121 8864,5838442,398186,6454 8865,6418819,234765,8500 8868,5296127,811934,5834 8871,3334792,336704,8748 8874,3397034,621494,5683 8876,5799075,39743,6244 8880,3213530,604456,8027 8882,2783696,583390,7600 8885,6313334,594170,8507 8889,6540714,858103,8645 8890,9806192,613830,6154 8892,1288923,711255,8584 8897,9800399,174197,7061 8900,4285405,928456,9143 8905,340880,258039,5792 8906,10301510,163362,6240 8908,5566262,747924,6652 8909,1823606,906351,5788 8911,4870748,443715,8855 8914,8827910,853612,9154 8916,6485237,365943,7337 8921,1521330,380111,9163 8923,7728788,333431,10116 8928,2809256,901078,9057 8933,3368324,704645,5688 8938,2214368,196660,10442 8942,823213,701984,8977 8946,1956134,415031,9692 8951,4550737,713067,9482 8953,7951695,13175,9057 8958,3629429,107847,9462 8959,3093900,932264,6654 8960,8796110,156797,7522 8961,269330,53516,10506 8963,698340,266494,6444 8967,7590763,689384,7685 8971,6710228,531978,5784 8972,4480336,172129,7762 8977,6572855,40983,7672 8982,3910411,753821,10682 8987,1372292,876010,6822 8991,3965522,926938,7001 8996,136443,574378,7964 9000,6210673,65549,6021 9001,9392526,76600,6336 9003,3955935,804964,10426 9005,2221611,419160,10174 9006,7129143,171545,8373 9008,6394468,526462,7913 9010,3465659,55185,7759 9011,8323206,342724,6141 9015,10158999,862523,9125 9017,6055410,611594,9513 9022,189562,475849,8516 9025,5716273,155963,9934 9028,10404254,768856,6635 9033,6260020,204579,6556 9035,3138214,756780,9788 9036,4817229,857132,7947 9040,4543610,689230,10304 9043,8972527,556190,6214 9046,6750410,211820,6826 9047,1110852,10766,8106 9052,3980254,184643,7814 9056,4011265,759742,9224 9060,8587282,410676,6390 9062,10176440,583401,8426 9067,10512034,691354,8850 9069,7932922,907839,7669 9072,1665134,675507,7702 9075,5042371,10211,7126 9080,2211805,186385,10072 9082,4683542,883956,9939 9087,10436700,750792,9835 9092,7216666,737965,7020 9097,10025115,754218,8026 9102,8477280,669397,5850 9105,3378487,872837,6027 9107,6330580,90785,8209 9110,4891188,456956,7121 9113,2736517,732624,6724 9117,4336116,295036,6648 9121,3428093,264429,5815 9124,5689723,613207,7797 9125,535650,192011,7587 9126,8157563,46066,5841 9131,2296832,266343,9215 9132,7100010,486242,5987 9133,4535070,328702,6873 9138,8362670,462891,10217 9141,9145037,700666,10413 9144,8471895,230727,7671 9149,1172790,702372,8265 9151,4516087,370151,9655 9155,2362281,692525,6340 9159,10172763,414279,9500 9161,9019401,320810,6116 9163,5494653,466895,6345 9165,503872,642890,5824 9167,1162742,62499,7439 9168,2090959,840858,6358 9169,4104787,512418,7093 9174,8150180,427399,9361 9179,6845193,638276,6289 9182,8315552,713067,9745 9185,8015250,818570,6609 9190,2320106,779538,8932 9191,5297393,730894,6507 9196,3558009,741575,8192 9197,8623269,419591,9397 9201,2136904,732089,10215 9202,3538253,616766,6058 9205,6881492,928018,7031 9210,3419439,111004,8609 9212,1855084,662409,9545 9213,4532700,854188,10303 9215,6152934,750386,8918 9220,3704827,127285,8977 9222,2352516,447103,9839 9225,10413837,743127,7169 9226,5298372,362483,6551 9231,6871633,717769,6722 9234,9430913,213320,7887 9237,2041728,647076,5827 9239,2949419,136515,7238 9240,1974007,709662,7686 9241,4542728,749732,9580 9244,9997878,777702,6688 9247,10549403,390505,10179 9251,9212082,155464,10242 9255,1283947,251286,10558 9260,8654759,865587,10468 9262,1682774,530298,9163 9267,7357818,113111,7372 9271,3736906,661287,9068 9274,782238,683512,9104 9276,8834000,673392,8731 9278,5714315,527983,8825 9283,4759538,928456,8382 9287,4208702,94811,6839 9288,1585957,460747,10131 9293,7964673,579669,9494 9295,7632815,180736,9022 9300,1662131,592445,5689 9301,2561004,721000,10304 9302,9245187,332930,8018 9305,2852744,219105,9874 9310,2083765,361927,8069 9313,275970,317429,7631 9317,1351433,445407,10187 9322,5286561,358149,10655 9325,1957413,278811,8156 9328,2120754,234895,7574 9330,9470998,837976,6797 9335,1923219,567674,9378 9339,9437150,526722,8430 9343,8557887,297375,9351 9348,4594565,554551,10645 9352,9021184,42632,6422 9357,4726520,28113,6338 9359,8916507,261570,7467 9361,9818544,469519,9178 9363,9006232,539332,9449 9364,8819247,68300,7254 9366,1978438,185625,7672 9368,1784717,847903,10603 9369,289248,379228,8554 9371,6256714,31544,7729 9374,5512131,605331,9608 9379,1103517,883717,10038 9382,9445172,178703,8961 9384,10162100,418145,6612 9385,5232070,92122,8632 9386,3573826,627609,7201 9387,5490019,639120,5618 9388,10572936,411960,6702 9389,8862346,21042,5854 9394,3350243,558363,9502 9395,1187024,578713,9475 9400,998375,121019,10364 9404,1176691,188225,8377 9408,10198289,545393,6555 9413,3836745,725857,7593 9414,7497948,184281,10617 9419,5222860,115359,9689 9423,481696,849411,8612 9424,10308093,408679,8382 9429,6783285,348040,9721 9433,5379424,103123,9215 9437,7418657,127302,8441 9439,7199954,877466,9263 9444,9081273,489989,7351 9447,427201,849489,7411 9450,1757854,515585,9860 9453,5785631,491919,10582 9457,3779024,309144,6122 9461,9173595,253182,6414 9464,7336171,478734,7876 9466,6937762,413012,9251 9468,10602176,193244,10470 9473,10605655,124234,7159 9475,7501876,265731,7244 9479,3833909,84935,8293 9481,2844171,300088,6570 9486,5854174,491932,5989 9490,1492016,686353,8161 9495,3752123,597732,10055 9499,2939347,497859,8848 9500,915293,535297,9962 9501,6270561,588443,6460 9502,9742952,275430,6634 9504,997347,868008,8938 9508,9061653,673612,6981 9510,5496321,479876,9231 9512,9878098,417741,6907 9514,9427696,248464,8843 9519,8759271,460799,5915 9523,2369757,277160,8229 9526,10491102,707896,8238 9531,307165,613814,10367 9534,7155027,231756,7240 9538,2318115,164929,10254 9540,5862498,133812,8971 9542,1510395,374650,7730 9547,9654570,290558,7417 9551,9605398,5000,10694 9554,6346523,859893,10149 9556,6453931,401452,7207 9561,2019459,69633,7472 9562,6135208,242529,6811 9565,9185095,472822,6955 9568,6612926,210679,9743 9572,6837613,824137,6907 9573,6738158,673437,7874 9578,1885143,874264,7667 9580,1594063,206510,7443 9584,3717278,301923,8179 9586,9251153,447863,10278 9588,6314,803060,10448 9589,9395382,327942,9903 9592,8931002,169197,10033 9596,8417542,872230,8379 9601,6405307,733980,8342 9606,1584114,275549,10216 9608,2805187,487645,6957 9613,5679539,691425,6807 9618,2609181,327692,8303 9622,1241780,552757,10531 9624,7148937,822753,7565 9629,4276987,452259,7666 9631,3754042,804127,8569 9632,7434517,370605,5672 9636,4298610,322671,7919 9639,5468982,861692,8714 9643,4789457,697038,9737 9646,6734167,579244,9569 9649,794424,596642,8007 9652,9616521,316440,5859 9654,1616762,587400,7085 9659,430209,804846,7668 9661,301322,167507,6151 9663,6517182,906735,10057 9664,8350756,382344,7919 9669,6101751,578591,8063 9670,3534369,800348,10624 9674,1631483,341149,7748 9679,3252707,268732,9920 9682,4064738,393721,6819 9687,6584606,616611,5624 9689,7242430,318725,6366 9693,6346728,472612,5919 9696,5224860,77829,7849 9698,8546930,610472,7747 9700,10454552,381792,8039 9705,439995,663921,6091 9708,961532,31086,5810 9712,5394912,166868,7177 9713,3993670,932062,8983 9715,6859889,573800,9259 9720,10230584,845199,8064 9724,5008507,220865,10675 9725,2939536,501254,6195 9727,6772571,840327,8355 9729,802973,748238,6467 9732,10280971,346810,9139 9736,7597042,404961,9914 9737,3801169,777849,6218 9739,4389269,749754,10489 9744,8550811,311460,6559 9746,2153480,438108,8497 9751,185736,285206,6514 9756,6211942,729913,10461 9758,10222199,409044,6697 9761,7825646,920890,5663 9766,1834458,406291,5664 9771,2909049,603123,6403 9775,2228904,548923,6838 9778,237081,501113,8560 9780,4016531,895340,6536 9782,4559024,669951,7107 9787,2122102,634284,8151 9792,9922859,468284,7005 9794,379001,109812,5852 9797,5505930,510453,6395 9800,4389896,773443,9587 9801,5047898,408653,7604 9806,9136610,625017,10310 9811,1204031,699241,8994 9812,5956410,868761,10193 9816,9593864,265475,6715 9817,10541359,773335,5769 9821,7260201,446105,7293 9826,7902491,100614,7471 9830,4115157,358249,8890 9831,1512974,57417,6985 9834,3982200,95691,10386 9835,10215727,689973,10635 9838,8811602,829530,9678 9842,5286097,662996,9004 9845,8799103,187760,7041 9850,8048795,690787,8921 9853,2797014,574684,6230 9857,7824069,414065,7902 9861,7786657,154258,7600 9862,10167299,215946,9123 9867,8815689,723398,9768 9870,6304214,880115,8058 9875,1940447,285208,9169 9880,802235,288195,10221 9882,696573,9290,9333 9883,7271864,826864,10049 9887,3008762,348678,6348 9890,4096115,498476,8876 9895,10497425,510285,7838 9896,1695804,123406,7158 9900,2703396,231325,8220 9902,5901852,862200,7485 9904,4003299,756746,9867 9908,1515771,699735,6415 9912,2206522,625159,7508 9915,8125052,755791,9826 9919,802434,355121,9225 9921,624768,436417,8819 9922,1904897,747824,8229 9926,6395527,283155,5979 9928,3087481,823671,10638 9929,1769271,22327,8441 9932,1574471,180610,5756 9936,6708237,874816,10238 9940,1612914,743636,10027 9942,9951879,527581,9402 9945,4629329,273224,9529 9946,3741058,741285,6094 9951,5109652,835528,7969 9953,10589599,199583,6623 9957,7466127,167485,10442 9960,7124287,823275,6072 9961,5495796,347396,6181 9963,7968124,302147,5730 9968,5807371,861228,6975 9970,6297408,718066,8760 9971,4689047,697768,7537 9973,7890437,886702,5776 9975,644120,930922,6800 9977,5054620,646155,5871 9978,9848021,151334,10489 9981,1968964,261263,5621 9984,3965554,665320,6368 9989,7036996,63833,9266 9990,5379631,218406,10336 9991,124935,896809,6366 9995,5312867,33722,5916 9998,3973309,759043,9126 10003,5342473,5453,6626 10006,5978842,151376,6305 10008,3187442,110596,7090 10011,3568831,918933,7082 10013,1984505,831126,8540 10017,9089624,713297,9700 10021,6568424,116841,8150 10022,1576165,720289,9396 10023,2219372,209520,10222 10025,5139413,30693,6476 10029,8128136,809382,6112 10030,2881348,721159,6875 10033,1618273,119544,9220 10035,1341068,490139,9766 10038,1488702,671828,8092 10039,10387956,274628,8881 10040,3072673,196233,5899 10045,3100153,631896,10137 10050,9318889,414858,7541 10052,1895536,210748,6753 10057,564806,706189,5912 10060,1420076,200223,6085 10061,759265,898250,10681 10066,622389,107148,10138 10068,7943944,27151,6122 10073,4129434,871993,5757 10077,3846444,293001,8695 10080,211226,537275,8991 10082,9138623,17431,5627 10084,5148149,925511,9626 10086,1757608,471083,7061 10088,4115612,766067,7181 10090,4941243,631496,9243 10091,2321648,312909,6259 10092,8539826,845925,10198 10096,4252293,743015,10333 10099,8969383,317013,8832 10103,1484913,366118,9658 10104,10100950,354647,10482 10107,8243202,564645,9635 10108,21061,388227,7956 10112,1248751,430359,7249 10116,3386518,276850,7202 10120,10216252,11806,10600 10125,3011220,59513,6311 10127,1199665,675348,8608 10128,6599271,667515,9510 10131,1207734,381665,9006 10136,3229777,153425,10601 10137,7099448,563300,7024 10142,541821,390217,7525 10146,8469776,436178,7432 10151,1815768,320899,8315 10155,6481767,412020,8029 10156,7263133,420942,10432 10159,9360709,886772,6085 10164,1490357,307995,6381 10165,319376,67067,9848 10170,8113371,788641,7553 10173,9991361,787054,7580 10176,9016558,89518,9820 10181,5834269,730634,7698 10185,7148381,143526,5639 10189,2050876,95564,10021 10193,7921148,591267,9900 10194,9405749,877326,10629 10196,1294148,285027,9073 10200,1019041,348199,6316 10203,8725170,627414,6935 10205,6632928,216077,9147 10208,9346758,915533,9992 10211,4616298,714057,8090 10215,8374266,408646,9084 10219,5026787,221486,10442 10220,9182495,801068,7363 10224,7128800,606530,6128 10227,2623292,738361,8522 10228,2020463,557204,7249 10229,5036493,511733,10066 10231,6438215,867613,9337 10234,6074701,368473,6708 10239,1273364,905774,5961 10241,8450858,4114,8066 10244,821906,619210,10206 10247,4667490,886052,9503 10248,10597506,215805,8932 10251,1179301,416971,8362 10255,1075512,745531,7516 10256,5153925,735875,8885 10259,10475355,679834,8706 10264,6451316,77410,8472 10266,7442083,614459,7841 10270,4161347,232778,8023 10273,6891195,169184,10560 10277,4528417,504547,9239 10282,3175650,673587,6629 10284,6731505,120749,7629 10288,10287408,2079,9641 10292,4365347,933291,10270 10297,6710928,241746,8137 10299,9802952,714105,6464 10302,8267196,483314,8642 10304,8337610,193882,6062 10306,5152176,217305,10002 10311,9153494,338148,9549 10312,1985934,539047,7540 10315,6713836,310353,9349 10319,2221160,148991,5732 10320,7369127,673913,6805 10321,6480296,300702,6864 10326,2405816,737073,6629 10330,6920577,674923,9944 10334,1012709,785108,6928 10335,2125211,694456,9908 10338,10377233,648055,7629 10339,84584,185647,7498 10340,3478462,487196,8683 10342,2649231,339260,6766 10343,1102285,542893,10129 10345,10344830,606262,8539 10350,8508526,226072,6043 10354,2531088,106555,5744 10358,3333426,545199,8682 10362,9770324,232503,7949 10363,10255761,608406,10533 10367,10478793,381421,7233 10372,5742784,257505,5902 10373,10533451,890874,9001 10378,8729260,56473,7958 10381,4307333,876300,7012 10382,5586213,510215,7680 10383,5888413,687445,9715 10385,3774858,321742,9832 10388,4127014,615048,9592 10391,1489339,715012,7667 10396,9441020,162472,9546 10397,5253318,263954,6368 10401,9415569,933054,6796 10406,2097300,912497,10179 10408,8242542,853018,7336 10411,575815,883036,8609 10416,10445196,735055,9184 10420,6793798,477622,7958 10424,4416539,135507,7093 10428,437074,419656,6782 10433,2869568,732676,7521 10436,1351843,923077,9367 10437,4657479,535518,8247 10440,2993096,222929,7564 10443,8926696,147230,6659 10448,5934406,717557,6652 10450,5769980,798521,6916 10454,6876825,401064,8793 10459,8769541,388742,7320 10460,1036910,891460,6572 10464,9200752,620672,10238 10466,6528372,351372,10314 10468,9560428,297438,9062 10469,2121168,384100,5899 10472,8333658,188483,5625 10475,9298036,862068,7002 10477,8883406,931454,6884 10479,9580860,644181,7323 10481,7938720,599837,7751 10484,10189565,736854,6548 10487,3162442,769228,7065 10491,774927,930226,10186 10494,9435584,802807,10431 10498,1174100,538511,8334 10499,10562694,475213,6345 10504,10106160,860861,8663 10507,3495280,478126,9282 10509,6716056,369038,9620 10512,3854685,741515,10386 10516,5549647,144303,6287 10519,5330474,359626,6623 10523,8464188,99468,9000 10527,9603100,104007,10229 10532,3249674,41915,10628 10534,749439,85688,8051 10536,3203984,508142,8089 10537,4895324,840335,8901 10538,6669701,367739,7007 10541,5977629,759670,5886 10543,8346396,217190,8385 10548,10369974,616052,6993 10549,7325667,866312,8534 10551,8775425,915042,8901 10554,5510389,878205,9639 10557,8365570,845158,8403 10560,3953557,542878,8859 10562,3748894,346205,8391 10564,1400450,737791,7122 10565,8815207,369607,9430 10566,8793578,690278,6045 10570,3385070,92340,7706 10574,7184382,725690,8948 10576,8631778,89677,6935 10579,10358208,466524,9068 10582,5664847,208847,7845 10583,9712606,173543,5928 10588,1518651,494875,7958 10592,4278673,819683,6701 10597,5997222,157930,9277 10601,3451457,131122,10211 10602,9060958,285353,9230 10603,6394099,845108,10206 10605,7993593,297061,6778 10608,2882426,120687,8841 10610,9781412,101315,8364 10614,6836873,694819,8251 10616,1977749,192175,6844 10621,2844033,453466,6553 10626,818061,219425,8302 10627,9832267,600794,8266 10631,10431796,182504,9254 10636,5702233,772879,6515 10637,4746759,766146,6464 10639,8793521,453035,8231 10641,1823099,149667,7223 10644,8178779,790379,9175 10646,1776084,268849,8465 10651,7556935,182758,9991 10654,3939013,109322,9855 10656,5473623,375047,5737 10660,4200193,279475,10558 10665,3485338,178200,8962 10669,9600170,304888,8328 10674,10601371,88684,6767 10676,3515422,493526,6007 10677,5930723,904808,7590 10680,1916287,909801,10490 10681,6891180,50749,10337 10686,3841646,542516,9371 10691,7365310,782838,7844 10692,7557911,485938,9689 10696,8090909,641531,9631 10697,8139026,537812,7691 10700,4711049,67403,8905 10701,7553524,260578,7033 10702,10350610,746574,7463 10706,4533081,9111,9096 10710,515429,212773,9364 10711,7364369,411690,8895 10715,4685065,790049,8446 10718,4995460,654165,9312 10723,10289989,200648,8543 10728,9952492,453714,7571 10731,282819,365578,9248 10736,1346453,740983,5669 10740,4081024,635031,5854 10744,3552819,875946,9008 10749,1177190,550694,9207 10754,8745635,834593,9088 10756,4791288,263423,6508 10757,3764932,217882,7564 10761,6746974,365901,6518 10764,1647314,342618,8424 10769,3888689,202772,10107 10770,29485,815426,7983 10773,8086927,901434,7027 10776,9367745,322222,9423 10778,1855876,286769,10279 10783,3559156,69797,9492 10787,10240721,11736,6205 10789,8417046,167316,6399 10791,5356482,523223,5891 10796,7945019,430621,7723 10801,6407966,411300,8531 10805,1003377,748442,6994 10810,4755487,215949,8851 10815,2696269,380181,8293 10818,10607968,103045,6120 10822,2771625,426301,7083 10825,8660950,911034,8294 10826,2582947,744299,10421 10831,9559504,380448,9409 10835,5493652,417561,10686 10838,4170722,305798,6199 10843,5389240,346205,5738 10848,4522162,124955,5970 10851,2132049,336479,9252 10854,1322205,518584,10046 10858,2784496,552531,10167 10860,2038520,190744,8819 10864,10136888,493203,6603 10866,10361297,620544,8276 10871,2463272,250675,8860 10875,4125212,606984,7746 10879,111917,900633,10575 10881,9142064,53396,10436 10883,6807355,617364,5935 10886,9549866,347071,8974 10891,8690941,895025,6903 10892,7492049,19857,8651 10896,827095,723009,9558 10901,7487201,620008,7720 10906,318762,201975,7535 10908,1261242,360728,8254 10909,4056084,862902,6370 10912,9609254,775233,7312 10913,9346581,395980,10278 10916,1636373,272681,7152 10920,3503179,553183,7750 10923,9051757,468230,5964 10928,9960313,773572,10617 10933,10372804,910793,10402 10938,1431420,492155,9278 10940,6605411,595905,8513 10942,5756896,614302,7427 10947,4175280,694630,7846 10952,3525960,448093,6022 10956,7452747,896123,10023 10958,4525520,421401,8610 10960,6486913,608357,6097 10963,9020997,900558,9154 10964,10231736,225880,9630 10965,5429119,831121,8196 10969,10144622,918015,9917 10974,6478021,30374,8763 10977,552904,390892,6882 10980,9236299,232249,8617 10984,9033144,829188,6108 10986,9852356,852771,6951 10990,4501451,675415,7757 10992,4220629,759760,8487 10993,2008796,49729,9578 10996,8986923,613352,7120 10999,2309809,723888,6532 11004,6433884,352791,9553 11005,5376503,711530,9592 11006,170470,364104,6259 11008,788777,776073,9106 11012,6102597,406758,7190 11017,4453161,362461,9240 11019,4324339,257063,9866 11020,10437161,158526,5902 11022,3446479,71131,6838 11023,6155385,174795,8879 11028,141249,816962,9594 11033,9900544,385669,6293 11037,7331494,576778,6646 11040,1500447,493542,8309 11045,580904,586491,10578 11048,361748,847044,9202 11051,8154643,781286,8506 11056,8517387,773485,6842 11059,10004028,109509,6755 11064,1929078,537457,7112 11069,1267799,886583,8331 11073,130228,149467,8004 11077,1960452,699828,9785 11080,2090974,251551,9538 11085,5165604,902122,6191 11087,5952506,693078,9895 11088,10388726,220894,6020 11090,3839622,905146,7765 11093,6422071,188798,6529 11094,6184542,691956,7737 11095,5751726,785380,8361 11098,6871867,448331,9586 11102,345577,73841,9410 11107,7306260,826698,7917 11108,7256217,138755,5640 11109,8009392,769597,9396 11112,10445384,559975,10438 11116,3009616,95568,8490 11121,9417944,703542,8913 11125,1297998,655524,6906 11126,2643208,96666,8266 11130,4417564,928879,8054 11135,5490829,225883,7211 11140,8247887,532209,10098 11145,8886734,446640,9955 11150,6691807,614590,9829 11155,3380168,191532,9970 11160,8177920,652971,6843 11161,6075865,666123,7693 11162,3892879,214001,7096 11165,19188,565708,8178 11169,1652547,244093,10528 11174,3849510,56361,7293 11179,5678768,121886,6785 11180,118075,752122,8641 11183,3238443,208438,6208 11186,6982731,257259,9398 11190,434668,82732,9394 11192,1176303,183103,6436 11194,6981547,115695,5903 11197,9708359,788083,9248 11202,2063533,377673,6850 11205,3575412,570001,10655 11207,2604103,139043,10331 11211,2009094,76972,7840 11216,251380,874563,9367 11218,1231252,508444,7036 11220,9246491,804443,7955 11224,5065787,177419,9718 11225,7232207,920360,8149 11230,3256692,471300,7571 11234,9037990,458275,8472 11238,9416605,43608,9479 11241,10423010,809454,8168 11245,5280800,189676,8781 11250,7570966,433288,7392 11253,7241038,340209,8841 11258,4880695,507110,10690 11262,7541588,426507,8593 11266,3255301,754210,7924 11269,412452,21603,6464 11273,4247568,151180,8056 11278,6771607,851749,10650 11279,9252676,50075,5727 11281,8273187,546288,6430 11286,9573504,205012,9703 11288,7348748,438670,7950 11290,7670479,634807,9336 11295,739978,112927,5638 11299,8871770,821262,6749 11304,9838347,492342,9644 11309,7903460,602924,6600 11313,2931276,165049,7110 11318,7081702,397437,6994 11319,963899,874682,5760 11322,5102765,922899,7554 11324,10021403,274769,8585 11328,3386700,95219,9957 11331,10499560,311601,6225 11335,5015824,461338,9305 11338,8743884,601976,6919 11339,5243153,744441,10081 11340,1911754,161562,10002 11345,9202512,274524,9546 11349,2756165,250380,6045 11350,3775316,289829,5711 11353,9720226,921846,8620 11355,10367692,410659,5982 11360,9924497,367645,7572 11362,6242674,239379,10449 11363,384677,207488,8832 11368,5037091,10442,9632 11371,6358672,643732,7464 11373,817136,6439,6138 11374,6820347,234605,10058 11376,10406439,592074,8252 11378,9180567,906393,5747 11382,6168494,141171,8128 11384,1344103,758068,6973 11386,942502,605077,9603 11391,9564451,435920,6505 11396,3393017,529571,7650 11397,4413974,189506,8969 11401,5550047,760937,8877 11404,1650519,388969,6315 11407,8562770,678884,7523 11408,2144626,390558,8672 11410,567618,681754,8741 11415,9495234,139326,9218 11417,6707873,689086,6065 11418,720609,782917,10489 11420,1055250,438080,10657 11424,8909134,434156,9031 11427,9701656,252471,5627 11431,8731717,31133,10598 11433,6778296,264619,6785 11434,5125412,532921,5929 11438,312562,94375,9502 11443,7902157,917698,9778 11444,3168719,89258,7807 11445,2972253,265356,8065 11449,5661314,700016,7935 11451,10505911,578918,8364 11452,4995874,150273,6120 11456,3274273,488759,10324 11457,3781574,445160,9586 11459,1036304,131076,9765 11463,2731922,522349,9070 11467,1603725,300899,10347 11472,8389474,256495,6472 11477,7439637,452096,6898 11482,2180473,47395,8567 11485,6584121,783863,10643 11487,1409488,488769,7906 11490,649326,874050,10130 11495,3878259,786368,7112 11499,6628649,613456,7200 11502,8666784,153923,8602 11506,878769,885561,7026 11509,3142421,739235,9565 11511,9152478,74254,9250 11513,7118652,931427,5749 11516,4837337,457856,10149 11517,8201759,787914,6107 11518,6429176,215980,8505 11521,6487414,568367,8169 11526,1044494,173089,10022 11531,8441950,540235,7176 11536,10189562,675261,8863 11540,8419393,528509,9874 11545,8422765,568285,6634 11548,7162359,196211,8729 11553,2859867,73220,10522 11558,9684712,214179,7553 11559,3432347,272999,8892 11563,5003953,833775,10572 11564,5776866,369620,7838 11567,8650893,450204,9049 11571,2550463,750125,10525 11576,196997,206434,7268 11577,7785751,758867,8738 11579,2991792,14380,5651 11582,47099,667292,7923 11585,7739607,505200,10421 11586,9570416,339182,5628 11587,7925114,745504,9401 11592,2701098,887497,7929 11594,6603383,284066,9800 11596,4748981,767268,9671 11598,5605625,755387,6029 11601,894539,229580,5727 11606,8912432,432913,10375 11610,5151227,40061,6094 11612,4886135,146388,6065 11615,10107824,37292,9621 11620,8650208,114843,6405 11623,5160977,546700,9502 11627,10275398,47116,9488 11629,1592758,728186,6536 11630,3397352,167846,10500 11631,7290906,508481,9057 11636,5126034,564098,8772 11640,5794397,459075,9611 11642,2255887,607105,9610 11646,4745660,304171,5678 11647,8824848,462986,9118 11651,1985336,618588,7192 11656,2702760,115209,5678 11659,2777228,706598,9430 11661,5073040,678948,6747 11666,1362698,167593,7801 11669,6287453,736863,5848 11674,9123582,515726,6730 11676,8450673,177842,9746 11680,9314587,669408,6649 11684,9617278,793456,7569 11689,8426500,635331,6961 11694,10626943,517718,7920 11698,1620873,528603,9862 11701,3685610,13735,8507 11705,8956390,475065,10377 11706,9512195,539365,5935 11708,312949,2537,10326 11711,9784091,638341,7345 11716,10000573,768935,6491 11719,1795067,49126,8036 11720,1861803,357272,5891 11724,4042220,332305,6063 11725,5099596,289846,6185 11728,5829547,553736,6877 11730,7659110,841202,8401 11733,6841804,221010,9391 11737,4030231,909325,7962 11739,10221322,553438,5943 11743,1102068,165650,9997 11744,9139551,892469,7031 11748,10208008,150541,6009 11750,5340376,173766,6570 11752,6746123,284345,6659 11756,8058389,393806,7248 11757,9534817,647427,8126 11759,7917865,63944,6730 11763,789464,622440,10551 11766,214385,335715,10692 11767,665627,886685,10014 11772,8429469,534329,7042 11774,2642557,877390,10031 11776,9537974,930820,10407 11781,3966876,877106,7162 11785,4762594,200695,8108 11789,7905880,203172,10485 11791,7156537,651044,5854 11795,10588916,758161,6462 11798,8477394,168504,9491 11802,252736,281707,10038 11804,2302719,77808,7853 11806,2372685,455141,9481 11807,2781206,42323,6974 11808,10651827,129811,7031 11812,2277358,708402,9427 11815,5998404,602107,8063 11818,7662930,432832,9517 11822,7512540,683830,5658 11826,2972245,552639,6381 11829,6565694,395435,6206 11834,4943933,496771,7740 11837,3152623,294249,7778 11840,8877491,462485,10534 11843,3084315,932731,8684 11844,4418324,454831,9104 11848,1613980,51794,8030 11853,649331,292937,9875 11858,91815,856974,6689 11861,5208107,229157,8970 11866,8688305,465133,6519 11867,1537879,712165,8835 11872,8222197,270669,10042 11873,3368550,431588,7361 11878,6261123,78702,8891 11881,7071846,213164,8097 11885,536491,311099,6158 11887,9152916,353216,10384 11888,6016356,506388,7596 11891,3693650,787715,7179 11895,1158814,44852,5993 11899,4601399,437739,8721 11900,9730948,532086,7793 11905,4235117,874258,10644 11908,8882499,679470,5795 11910,10005998,312800,9981 11913,1612673,119621,9025 11917,5159049,255955,6871 11919,2644013,135788,5982 11923,9629015,412717,8471 11926,7093807,653785,6462 11929,470811,690975,7836 11934,2414566,719586,5967 11937,8141347,361013,7794 11941,8111631,591090,8813 11945,1916404,266761,8802 11947,9579469,577510,7654 11952,8498230,187550,7752 11955,2260931,756426,10260 11958,4009226,398292,9730 11960,3608902,334888,10132 11964,8004517,785186,9727 11969,2291344,338612,9227 11970,3968304,506238,9139 11974,4895603,460608,8236 11976,5932094,249313,9866 11981,512677,314779,9585 11984,9994066,346513,10017 11985,3910478,373363,5911 11987,6840117,206135,6146 11991,3294462,693769,9349 11992,7612107,210903,8832 11993,1189964,64146,6250 11996,10247755,443196,8943 12001,6300293,779729,8867 12003,4086852,656137,6613 12006,9166602,326889,8886 12011,7421901,237958,5947 12016,1882480,358679,6087 12018,5578041,770411,7515 12023,9180658,3533,7778 12028,1748745,289202,7920 12033,9683836,547438,9948 12035,2286397,761647,7795 12036,9539694,182907,6700 12038,138128,550749,8214 12039,10158589,899035,8975 12040,10628587,472390,6611 12044,1741729,831944,10067 12046,1949705,649780,8360 12048,7697407,154775,6136 12051,6881245,929216,6586 12054,2219628,695093,7609 12057,9952123,516430,6795 12059,411657,897056,5930 12063,942858,938475,10494 12066,2959798,671095,9455 12071,3774437,57574,8510 12075,6994065,139865,6300 12080,2580758,795119,9407 12082,6092091,588645,9002 12085,9798710,448282,8014 12090,7141795,296406,9677 12095,6271778,364575,6430 12097,5552061,834255,10668 12099,6174523,118984,9680 12100,1346376,119508,7209 12105,6242092,11365,6528 12109,5621231,187797,5979 12111,5767422,252728,9820 12113,416355,33235,10465 12115,7835827,630767,8769 12119,4007093,772358,9753 12120,6835171,868906,5625 12124,5365255,730069,9996 12128,4437080,356823,6574 12131,7026504,508668,9555 12132,579119,298894,10121 12134,8517207,372416,7289 12137,10063782,628389,8897 12138,4643580,78247,7556 12141,6794840,290698,9793 12143,4578080,918474,7281 12144,1621883,659645,8224 12145,1754778,605973,9002 12149,2948417,296077,7792 12152,5564461,647544,10646 12157,8207191,542264,8477 12158,4176904,625326,10062 12161,3739315,686594,8253 12165,545555,245062,10419 12168,6783022,577692,9088 12171,8252445,645569,10386 12175,4838242,18791,6944 12180,419496,88917,7068 12181,9943179,401111,6000 12185,10541398,439594,9309 12188,1799748,459878,9003 12189,7469728,196532,8201 12191,7014236,426844,7133 12196,775590,405464,6551 12199,108579,42047,5964 12201,3327487,195510,7870 12203,7495911,810871,10452 12207,3462697,182030,7455 12209,1602828,207333,7805 12213,5924555,640171,6544 12217,3214587,183520,6525 12219,2345270,352660,5896 12224,267092,564312,9278 12226,999498,244036,5813 12229,4092222,470751,6863 12231,10342473,54957,8555 12235,4199598,704305,8859 12239,10329063,373097,9079 12241,10002023,57615,9766 12246,4763734,223725,8433 12250,7353087,701146,7519 12253,893306,925126,7095 12254,8824786,690266,7582 12257,10100604,308666,10490 12262,9032278,39296,6448 12263,497879,116895,9204 12265,6058488,195736,10583 12267,8354319,265420,7511 12272,8132342,766217,9889 12276,10098084,445449,8571 12278,6513540,274926,7761 12281,6423382,313137,6503 12286,5924100,901211,6812 12288,6067745,380960,7775 12292,1807,368624,6999 12297,1308893,549989,9671 12301,4072573,828763,10153 12302,6561284,143876,7214 12307,116647,376237,5801 12311,10241245,820792,7234 12316,248144,582679,8274 12319,3957685,41586,9977 12321,3515139,10720,5898 12325,1630687,328407,6899 12329,9915039,447475,8612 12332,5403849,920730,10338 12333,7235756,648029,9352 12337,6688598,315961,7483 12340,7784423,44487,8322 12341,8848570,902093,7088 12344,5538525,228173,6797 12345,8912861,704327,5784 12347,1099032,871366,9546 12352,7193404,346177,8313 12356,9265126,602839,9591 12361,4364175,317367,5672 12365,9727093,587299,6761 12367,8290032,574941,8550 12371,10054308,386276,8995 12372,390348,852872,9663 12376,21875,416848,9407 12379,9966442,83774,9884 12384,3157543,195085,8746 12389,5858062,11759,9682 12394,5953475,599797,9784 12395,7029688,847235,7153 12397,5501136,427862,6173 12402,1440316,471674,5991 12407,5116784,237559,7234 12410,2170894,493328,6972 12411,3701181,768741,6483 12413,5418901,646580,5637 12415,8696819,869750,9231 12416,8857168,532728,6897 12419,5498307,894951,7882 12420,7809488,536020,10366 12421,10224895,699794,9928 12423,924352,441595,7758 12424,4417113,77992,7462 12425,9125793,223657,6495 12426,10414393,705324,6538 12431,6650058,615923,8807 12433,1877976,854846,8863 12434,327582,387653,6930 12438,6764102,565879,8576 12443,475091,189118,6004 12448,10079208,52161,9274 12453,19799,361135,6993 12454,1108034,661014,8424 12456,4021877,576363,8510 12460,5895536,203168,8555 12462,4724317,837869,9935 12464,1128958,11270,8513 12467,1860465,289695,6499 12470,4249913,356098,6994 12473,10427397,260658,9493 12477,3778736,883793,8323 12479,8291021,605906,8445 12480,10651749,123683,7501 12481,3927476,544740,6540 12485,10422465,627309,5756 12487,8678029,342928,7182 12489,8353786,258102,7786 12490,10427348,747851,6946 12491,10150212,951,8589 12496,4444615,927671,5758 12498,10041427,612024,7476 12503,3709789,580563,8406 12504,4387384,634549,7399 12507,9210729,930436,9750 12510,7575849,255377,10300 12512,4214683,629091,9020 12515,4519710,715015,6077 12519,8342527,45322,9105 12521,2183661,488776,8219 12523,9139719,727950,6278 12525,2810526,540407,6739 12529,4112641,454563,8342 12533,8778452,361358,10204 12536,7291185,323005,6858 12537,10659182,51060,6538 12539,809840,882233,9872 12540,2065196,539371,5637 12543,4123469,260637,8086 12547,752524,862610,10405 12548,3473130,197773,6514 12550,6274825,741015,7469 12554,2492506,898877,7440 12557,879668,635628,6100 12558,6172409,751816,10112 12563,5770371,50040,10633 12564,1967266,284544,7164 12568,4585378,60757,10549 12573,9967642,217313,10524 12578,10599713,1817,8498 12583,6376134,162208,10425 12587,1568007,93695,5671 12591,8577225,561304,10586 12592,5001907,777050,6928 12596,3055939,113893,5619 12599,1392258,89671,9605 12604,4463220,544252,8959 12608,3049867,587376,8248 12612,8104218,748004,6032 12616,10281603,497448,7639 12618,3111068,490012,10213 12623,155978,728555,10483 12628,4953209,137049,5657 12629,1604494,887023,8021 12634,9508236,929518,8232 12636,6276049,897754,9467 12638,233274,906525,6257 12642,3306950,78262,8147 12647,1316008,374915,6273 12650,2132197,221082,6163 12653,8863896,878985,6987 12657,8720744,181883,9457 12659,5423912,461910,6474 12664,239451,709569,7676 12669,3344164,863313,7143 12674,5148420,908636,9547 12679,1556245,637760,7515 12683,3145352,256168,8511 12685,8634292,316168,5843 12686,9828416,363765,9227 12691,8338105,535512,9263 12696,5871954,170036,9955 12698,6105938,724854,9759 12700,7071508,546082,8798 12705,842255,811145,7647 12709,5685396,222575,6451 12714,10199849,126365,5628 12717,6027862,73519,6777 12720,6616729,416783,10232 12723,2402943,444412,7077 12726,9598787,671627,6954 12731,7550390,526773,10112 12736,6193021,324702,9686 12740,3855535,200867,9547 12743,5814862,161013,9627 12747,9743707,426175,7456 12751,9702736,59917,10435 12752,8769335,415445,9724 12753,8625949,839235,9606 12755,7378680,312132,10184 12757,119793,868727,9257 12758,5585998,514946,6139 12761,7089045,398294,6588 12764,8666996,578561,6083 12765,2508958,682590,8528 12770,1040966,150975,8873 12771,1130458,710380,8688 12773,7055653,405050,6060 12776,500210,751168,9696 12778,201493,123380,7007 12783,1938295,831421,9020 12785,7006679,538193,7646 12789,8581339,938444,10492 12790,4592487,819409,10082 12794,278554,112086,6783 12798,3473330,918003,7120 12803,604184,532398,6466 12807,1050858,273441,9207 12809,10368109,925256,10465 12813,5366635,220204,5906 12816,5425134,424087,6062 12819,3197611,788303,8503 12821,3097628,878047,6499 12826,1710382,794800,10479 12827,1925774,877607,6679 12830,276335,925683,9990 12833,4818327,661316,6283 12835,9523629,410584,7028 12836,6621472,235863,6952 12841,10194920,289795,10471 12846,4746440,477206,6113 12849,3523392,686637,9977 12850,2182041,213710,10225 12853,2690399,190891,7186 12854,6192701,686285,6307 12857,1511724,669453,8698 12859,2033292,283594,9996 12860,722990,348212,6830 12865,8054994,435449,5867 12869,8305486,11532,7136 12874,8067304,35888,10120 12877,7017950,816213,8888 12880,9548220,349342,8388 12882,9080965,114533,6047 12885,8026258,529204,9210 12887,8812203,41474,8941 12890,9724047,702452,9472 12894,7965067,21205,9796 12897,8471745,286806,6224 12900,7390329,194408,7024 12902,4871750,618656,6915 12905,1707624,795229,5647 12909,8548207,411812,6435 12913,1368007,834245,6541 12914,237690,477895,5964 12919,7102434,249393,6636 12922,8723958,927535,9448 12924,6407151,854185,7471 12926,4220754,602544,9024 12928,10296953,59104,10209 12931,3331150,474062,6871 12932,5827582,759771,8497 12934,9746596,526842,9912 12935,9369594,694308,5647 12940,846842,682580,8751 12942,8165878,458015,10567 12947,5673253,742690,9953 12948,3501984,899181,6774 12952,1589908,798219,9669 12955,9494099,172868,7438 12957,2315505,753062,6998 12959,5049892,363656,8567 12964,7777135,228301,9430 12968,5161358,492471,6825 12973,3762542,34069,8252 12976,6219505,10360,5852 12981,3490212,29925,9081 12985,5637039,26253,6653 12986,8209026,390064,8390 12990,1595547,518291,7555 12994,4500072,611694,10320 12995,7170421,437003,6500 13000,7640942,904672,6923 13005,1072714,135649,9598 13010,4423226,594104,9740 13014,4804111,819663,7480 13018,4075303,695090,8211 13023,8339077,170844,9279 13025,2147576,302280,7062 13029,5860270,719242,8120 13032,7902442,319392,5736 13037,1866054,229091,9033 13041,3630668,547751,8124 13045,2280464,779874,6401 13049,3682347,869106,7783 13052,9971054,305997,5689 13056,4253012,570753,5666 13058,638611,636407,6301 13059,10120983,788580,9434 13061,6227418,614967,5751 13065,1243447,263935,8235 13069,5406135,747578,5827 13074,10662975,741488,6899 13078,7854099,850928,9013 13080,780774,499618,10482 13081,8024987,211991,7523 13082,3756912,468919,10341 13084,8237,214668,7565 13087,3226375,428839,7951 13091,4078729,741447,8416 13094,9952102,609965,7606 13099,1250385,543964,7709 13104,8655086,70834,10559 13108,6009094,635615,6492 13109,7926879,366688,8163 13114,7538317,862334,10150 13116,9710179,616000,6795 13117,6967117,927127,8648 13119,2568174,765587,10507 13121,4858083,70722,9249 13125,10153800,344186,9578 13130,752426,750461,6664 13132,7546068,65611,10443 13135,10321309,80628,5950 13138,1989639,642439,7191 13142,8330139,271833,10369 13143,8931853,840862,9747 13146,7838758,670528,6452 13151,3107640,719002,10582 13153,3766809,405464,8283 13154,9503236,477914,8930 13156,5098836,9681,7992 13157,6773900,425167,9354 13162,5757288,337702,7732 13163,2374970,115429,5944 13165,4169888,323255,7962 13169,6278376,318269,6904 13173,3901938,547524,9972 13176,7291439,54889,8702 13177,2448662,847734,9674 13182,6369432,932525,6726 13184,4563294,30730,6310 13189,6192799,425776,9425 13193,10311882,1305,6384 13194,7812532,875287,8494 13196,2221445,469952,7486 13197,7493185,847747,9850 13198,582067,727808,5958 13200,648749,389898,7877 13202,2989706,692387,10579 13203,3359389,350689,9604 13204,6064930,77897,8814 13209,3206264,272363,10637 13214,1616616,758992,9908 13216,2500459,424087,8230 13221,9628938,449672,7780 13222,23398,681558,6335 13226,8004454,373926,8578 13227,4199596,137143,7632 13230,1699971,261188,10429 13235,1872791,552192,8638 13238,8003847,555016,6075 13243,1107851,487853,6985 13246,3095035,124185,9880 13249,7836250,363769,8381 13253,3680991,345640,8571 13258,10315126,227490,6551 13262,6327399,868990,6406 13263,5216152,559446,6136 13268,6629532,438697,10453 13271,10473751,226706,7945 13275,4550188,598892,9071 13277,10267033,882317,9305 13281,1114588,360770,9347 13285,4880898,488107,8072 13287,3529389,59293,9853 13290,8777433,132947,7850 13291,869247,237092,9977 13293,3753821,99046,10630 13295,8946955,202794,8958 13297,5176176,731448,6612 13298,3534922,24558,6248 13299,2334930,339233,9946 13302,1118103,277630,8092 13304,10532399,601206,9126 13307,10451523,359639,7591 13311,7861353,650176,9492 13312,8256949,157742,6969 13315,5047550,113488,10285 13316,9476066,370306,10282 13317,7611934,558366,8275 13318,6906093,543889,9815 13322,6985613,579347,5778 13327,7843735,131596,8025 13329,481194,279240,7391 13334,7536390,470404,10329 13335,392442,318044,7793 13338,8343489,521470,9232 13340,8495247,758197,7447 13342,10229159,477068,10456 13345,2709697,834557,7363 13346,5324329,294450,6679 13347,7422059,142195,10360 13351,3954722,73699,5964 13354,5291868,713979,10619 13359,10209670,688282,7972 13364,10225481,442503,6648 13369,9749777,730507,8695 13371,4914473,229790,6582 13374,8840172,309997,9581 13376,6627952,378697,10330 13379,681054,708710,7282 13382,1212393,601042,9701 13384,8597343,750338,10611 13386,3037879,795885,8087 13387,5869131,83808,8096 13392,2916525,364623,7068 13394,3890982,920860,9943 13398,8639046,792438,6166 13403,950346,588569,6271 13405,6877952,432226,7823 13408,1597481,97963,7707 13413,5837613,360384,8997 13415,4639074,446508,6950 13417,2454314,775972,7090 13421,1096326,910704,9540 13423,4942156,442359,8654 13427,9770599,582231,10405 13431,8676838,446129,8435 13436,7889091,853780,9339 13439,4347797,568373,8878 13440,7927380,357943,8670 13441,10111711,128160,7971 13445,3972229,534310,8110 13448,10510333,267687,7427 13449,8218453,579957,8389 13451,5727284,866511,8298 13456,6044768,298524,6675 13457,2232005,526262,8942 13461,4283127,256298,6519 13464,1221332,139991,10461 13469,6963313,323406,9309 13472,2163510,327912,8628 13476,1328365,79426,6326 13481,579229,664466,8024 13485,7489085,208950,7868 13489,1902262,759521,8451 13491,1643113,546470,7680 13494,9137012,422291,10075 13497,4366278,686272,9032 13500,6908303,892405,7256 13501,1880469,419447,9195 13502,8071980,602912,8051 13503,3244520,566559,8985 13508,320689,317730,6563 13511,2157293,792608,8821 13514,2317229,931519,6767 13519,5856520,646595,6550 13523,9207302,62620,9063 13524,774253,603258,6674 13527,8132942,388423,9569 13529,5982393,58979,8580 13532,8413188,563734,9145 13534,2237482,617040,6510 13539,6514127,897875,6379 13541,1184666,106633,7916 13543,3949101,53486,10102 13546,8837471,726495,6654 13547,2708938,498011,9133 13550,5118445,724024,9523 13553,9049912,414054,5855 13555,9181447,197549,9898 13558,1749222,345755,9683 13563,7534547,466509,6281 13565,9250058,924351,6290 13566,1957578,501444,9589 13569,2423485,811130,7130 13574,431366,348192,10184 13578,8618928,98343,8649 13579,4468757,853929,9366 13580,10519934,589865,9633 13585,6135259,405795,5790 13589,9709643,533878,6615 13594,4313118,862592,8142 13597,3497066,765417,9009 13598,8103517,687781,8008 13600,6239998,327323,6657 13605,7823977,464922,10642 13610,6489448,519309,9786 13611,1781747,745550,10299 13616,8839633,408195,9376 13620,6235685,733513,6669 13621,7365668,764323,7976 13625,6737894,69657,7704 13628,10447452,1294,6197 13632,1945765,674479,7501 13634,4613345,65902,10034 13636,4778040,418864,6829 13640,7981343,911207,6626 13641,4644031,817510,9097 13645,8061904,773232,7068 13649,894371,794175,5896 13651,10555722,923626,6313 13655,3974462,332637,7837 13657,3750010,809029,8073 13659,9578733,152943,9700 13662,10225946,671935,6167 13664,1941651,104966,8245 13665,9545957,648341,8897 13668,434179,532349,8312 13672,7448679,729542,9271 13673,6452198,158839,7266 13678,9741232,407631,10267 13681,5512106,858153,8117 13684,5067173,409515,6375 13685,740584,102797,9457 13689,3948687,790456,9841 13694,6140814,528224,8697 13699,1348913,833195,5872 13703,4266853,138891,8841 13704,10423276,602457,8811 13709,1288739,87813,6650 13714,1489877,729577,6965 13715,325453,837908,9272 13716,2706952,735345,6703 13721,3635543,186938,9567 13726,5404492,265354,9494 13727,2911185,400295,9597 13731,9958015,543442,7817 13732,10220633,464208,6566 13734,4049394,219851,8113 13737,5003371,366207,6656 13738,5185179,771300,7909 13742,8455105,206590,7638 13747,9436663,397321,7645 13752,3486121,309810,5668 13757,8200969,494914,8303 13760,3974907,448719,6369 13762,2508200,153923,8547 13767,5545610,800193,6799 13770,7252862,361144,8108 13774,4375316,649620,6334 13777,6068861,884523,7569 13781,1668496,890069,7813 13784,7365564,298286,8307 13788,9877958,212152,8330 13792,4334086,487081,6900 13797,4102532,842867,8705 13800,7799865,621125,8988 13802,9977482,513792,7074 13804,10645837,539459,8388 13809,8993237,888376,7839 13811,6787853,155726,9798 13812,193116,773904,6993 13817,7718408,684878,9825 13819,829548,382250,9931 13823,2708401,753550,8198 13828,5812982,101579,8531 13830,912389,355869,8529 13831,6844123,879585,7051 13836,3887793,553705,8029 13837,1176784,443299,8882 13839,8391455,883761,8544 13841,6674057,929769,9102 13844,1008709,70952,5983 13848,9029266,634084,9093 13852,10550068,464660,8992 13854,4395474,285806,6989 13855,6796993,93010,8033 13860,4587755,364716,6699 13864,4847493,784436,10460 13866,4977245,937918,7867 13869,88690,395267,7433 13872,9207191,426234,8130 13876,8121060,909408,7723 13881,1867108,903170,6243 13886,180732,328272,6148 13887,7389622,831645,7617 13892,2981104,929564,5946 13895,8676464,225226,9414 13897,5975195,149660,7728 13898,8002365,623173,5816 13900,8393537,550554,10385 13904,3802111,788407,6374 13906,4877762,649901,7091 13907,3955102,885820,8329 13911,10151841,688082,9040 13915,10471323,199046,7873 13919,8909359,657211,7656 13922,1971118,728340,6088 13924,9408844,605774,6906 13928,763186,269977,9021 13930,3820460,390410,9123 13933,8914944,811555,7517 13935,5879305,517954,10068 13940,7437442,837769,10255 13943,1298075,437129,5672 13946,6519738,867150,6875 13948,7529697,826653,8211 13952,10183011,836883,9698 13956,6198936,697730,8571 13960,10425076,314003,10642 13961,2653654,6674,6429 13964,8619176,35388,6486 13968,10603014,378651,8619 13972,7012211,200638,10062 13973,7846127,321058,9764 13977,5840807,690428,8732 13978,821903,830688,8562 13979,7091224,126413,7558 13981,9404690,753362,6981 13985,1157045,719759,5928 13988,4023717,867654,8870 13991,9374946,184142,10551 13995,4147821,667750,7179 13998,10045059,315796,10520 14000,2301938,477562,5978 14003,411827,676257,9779 14006,9844937,545826,6340 14010,2927087,929231,7205 14014,3071867,905178,6645 14018,3720352,159833,9868 14019,6171174,170703,9340 14024,1322046,1703,7870 14028,3342270,385218,8130 14032,10238787,270765,9573 14034,5509973,150646,10057 14036,709730,181527,9691 14038,10516891,878465,7913 14040,5280029,24980,8082 14041,1969841,587756,10478 14042,6534832,433383,6641 14043,240530,362200,10187 14046,6658905,675313,6464 14051,9127034,601383,8341 14056,5505888,373667,8818 14061,2289274,304806,6806 14062,4431228,128875,8201 14063,8895404,501609,10409 14064,1984347,571643,6116 14068,7862884,596422,10368 14073,10639632,544396,8691 14075,5166689,263566,7677 14080,4432782,793625,5691 14084,1622653,166494,5743 14088,2442014,452086,6962 14093,7683392,936449,5967 14094,3559837,209289,9421 14096,6255851,575111,6148 14098,8727052,452631,8174 14101,1861995,193352,6787 14105,5397181,265946,9763 14108,7579400,63453,8727 14111,6955747,607186,5663 14116,1011129,558803,10642 14119,6189754,202918,6058 14122,2211471,94884,7286 14123,6021268,438547,9807 14127,3260793,317418,10014 14132,1696617,118323,8183 14134,7651501,616742,9907 14138,3626500,75089,9400 14139,3768174,83427,7757 14141,9303663,542992,8342 14145,8169936,279649,7663 14148,5290925,247716,6885 14153,7643778,751240,7381 14154,7771978,780894,9216 14156,1325163,449813,10362 14158,8737898,716891,8109 14161,9377965,714114,9697 14162,10149659,233960,7810 14164,8982492,151445,9189 14168,5579897,771315,6078 14169,4520459,797989,9487 14174,9735650,229749,7004 14177,5104914,116285,8727 14178,8678372,764917,9108 14179,5486085,848553,7287 14183,9796774,752911,6720 14186,1832843,875416,5908 14187,544180,359459,7336 14191,3684992,504770,7516 14195,5599644,487926,9661 14197,5299692,535070,9969 14199,9692514,416648,9155 14202,5710290,4355,8578 14205,4157314,586161,8167 14210,8717861,642652,10240 14211,9459874,327453,8692 14215,9338518,803036,10427 14218,8559979,419233,7982 14221,6968796,493386,6976 14224,2978580,551800,9183 14227,1919161,77509,7513 14230,7578006,353265,6478 14233,376539,517778,6775 14235,1518443,462924,7259 14236,3418688,567375,9600 14240,5935091,175120,7126 14244,3725420,721785,10339 14246,1490376,363412,8791 14251,1210941,725954,10664 14253,3654078,33304,5783 14258,9992773,462753,10491 14263,7675926,654488,9952 14268,1043851,883565,9947 14273,488303,445613,9979 14275,8691206,677866,8931 14277,8512721,473847,7716 14282,4913712,467466,10604 14284,10653365,3345,7026 14289,9325607,851289,9062 14290,9915459,265541,7861 14295,8768454,877908,9782 14299,1051197,299666,8778 14301,2211651,929500,7897 14305,2861500,119010,6155 14308,8098718,701414,5952 14309,9533280,275701,6568 14312,9652531,22776,6780 14315,1097603,35521,6594 14319,1476561,586960,9870 14323,6565071,70259,5691 14324,5125762,851502,9211 14327,6993513,855005,9765 14330,1203623,843464,9096 14333,10655465,322465,6734 14336,1798366,701344,9457 14339,621482,185303,5844 14343,9980725,911083,7643 14346,3785811,74738,8603 14351,2402827,313494,7489 14355,2375902,367402,10505 14357,6851043,610760,8717 14361,5385332,214888,7953 14366,10373412,77257,7474 14369,8855217,283572,9608 14372,7631925,96032,7931 14376,9898330,836680,6309 14377,1137375,202269,6401 14381,8518248,75839,10097 14386,10491987,211499,9897 14388,8423082,550766,7488 14393,3393181,52202,6291 14396,1783181,501506,8441 14398,10382883,45296,6703 14399,5830548,639554,9999 14404,9952255,531816,9062 14406,10069800,855747,8892 14409,10206679,920428,6763 14412,8149558,755238,6278 14417,7243431,213684,9812 14420,7786979,61601,5735 14421,4002435,531393,9826 14425,3251402,518797,9723 14429,9564092,507779,10546 14432,2024975,415359,5702 14437,5128229,796310,9041 14441,7047683,418094,6764 14443,2776497,427479,8581 14447,991102,820372,8403 14448,4219471,792792,7650 14452,3652152,750171,9491 14453,2398690,935570,10332 14454,5480667,573245,7360 14457,9256941,377723,10650 14462,3314608,714389,6486 14463,2962605,888122,9125 14466,9320200,557118,10177 14471,10616940,286569,10635 14474,5919582,81944,9560 14478,6042508,439326,8963 14480,8844680,820865,7197 14484,8269148,552823,6379 14486,6360999,82853,7072 14489,8476454,62951,9367 14490,4128052,128846,6483 14493,7739618,457916,7660 14495,909759,602188,9002 14497,259831,425645,9151 14500,7486072,383324,5730 14503,2696655,237439,9831 14508,1782249,478109,8370 14510,3463025,323668,7994 14514,9461193,556617,6288 14519,8731516,236016,7769 14523,5452297,226206,6841 14524,1926908,365735,8276 14529,3344105,898521,6356 14531,8630670,352413,6732 14532,1026854,851347,9924 14537,2237051,385792,8985 14540,2994710,492421,8767 14545,886139,899488,9192 14550,8295526,687142,6590 14551,2270855,698201,9860 14553,5475389,419619,8245 14555,8619206,715211,8046 14557,8871458,703083,5776 14559,10066062,810615,6442 14563,6336763,156202,7390 14566,3602365,266984,6870 14570,4431037,212392,10300 14571,7662997,331777,8917 14573,6245787,876562,10541 14574,6555202,791137,8805 14575,1799511,754239,7267 14576,916486,299053,8150 14577,9134717,77442,5740 14581,6821,345620,9711 14584,2615393,618706,7485 14589,437050,722900,10015 14594,5906101,893072,6241 14598,4268046,894994,8132 14599,6389152,32367,7644 14600,8524392,760523,5795 14604,2973636,8527,10534 14606,10667713,73914,6752 14608,4742261,353435,9361 14611,9747425,719066,10039 14615,4013132,558156,7191 14617,751283,831518,9974 14622,2121595,250998,6115 14623,4115698,515113,9020 14626,398206,47563,8242 14629,9362587,868322,9573 14634,274410,95083,10286 14637,8388571,885795,6632 14641,3015304,339496,10468 14646,945693,242127,7852 14649,8894076,342238,9672 14652,2354820,621518,8282 14655,8201755,135015,10469 14658,7673032,48735,5813 14661,2466259,83613,7017 14662,8756857,102260,6039 14664,1070452,547949,9254 14669,5566503,88927,5793 14672,1390087,653299,9551 14675,6151972,281701,9149 14677,3767275,829747,7501 14678,4687882,380034,7718 14680,10421021,873668,6554 14684,4163460,852119,8388 14686,579828,454775,9532 14688,4219658,138911,10306 14690,10065527,528264,8927 14695,8521827,821052,8608 14700,5361,488449,8372 14705,379493,911593,9204 14706,6602958,499474,6788 14708,1324005,588387,9377 14713,9485631,208311,9531 14715,7234276,696687,9043 14718,6853034,259075,7710 14721,1976214,94514,6212 14723,422948,895375,7680 14726,8873306,111094,9411 14730,7466342,85660,8753 14734,8228777,879862,7070 14736,6908430,725569,7137 14740,7904242,320829,10336 14745,7959690,497561,10252 14747,7999784,60620,6155 14750,9764465,655977,6360 14754,5330398,87386,9852 14755,7500831,808937,5863 14760,8457019,489713,6869 14764,10254511,342381,10040 14766,9535815,579957,9899 14770,10182523,150476,8486 14772,9436270,117861,5622 14774,10659848,832475,7430 14779,3010848,334794,6510 14784,6976641,7708,10194 14786,8561147,891225,10431 14788,750292,813202,10357 14791,4795065,79775,6950 14794,4066051,841434,10598 14799,3084957,209484,7687 14802,1658837,929144,6713 14806,7549112,21331,6365 14807,6764758,262111,10629 14808,1587088,711807,9125 14811,6237303,453598,7120 14814,2079334,50749,8165 14816,2999062,341414,8196 14818,10225331,917350,8171 14820,8022326,631405,8811 14821,5448624,110549,7636 14825,727779,820422,8755 14830,6430353,466243,10518 14833,2999057,359480,10180 14837,8834123,875661,8048 14840,1750835,394193,6988 14844,1730202,255637,7036 14847,3495370,837912,9781 14852,8738287,920186,7567 14853,9000807,583735,10334 14854,8361809,118285,6438 14858,8141799,112059,10660 14863,8631317,931373,7573 14866,6970262,505773,8541 14871,4915165,248669,6846 14874,561027,546502,9682 14876,6091221,828967,9947 14881,5229213,629228,9135 14882,8496074,260298,6315 14883,3906775,226013,9054 14885,7887440,4620,7401 14886,2287014,634934,8418 14889,6873538,7624,9542 14890,9767430,552225,8979 14891,6516733,4417,8178 14896,62509,591429,9614 14901,6486106,790456,7044 14902,409627,849774,6988 14903,2037235,501361,5959 14904,7198681,635660,9872 14905,2771588,146290,10335 14908,409042,196238,7670 14912,8143768,117577,7660 14915,3956929,445161,9170 14920,3610715,513375,9816 14923,1870710,97029,8452 14927,7615637,893685,10388 14930,7151622,859635,7668 14932,7321739,542196,10300 14934,8826261,736806,7064 14936,7072841,717117,9168 14940,8492471,170334,6529 14941,147684,857987,8980 14943,7591855,742142,9233 14945,4218974,533524,9559 14947,406294,505281,6850 14952,10278971,130703,7781 14956,8480500,433642,9702 14960,937754,231964,9397 14963,8959511,839932,10504 14968,8385197,189575,7964 14970,808096,276930,9430 14975,4120356,180130,6712 14979,4369009,802726,5869 14983,2636858,523744,10192 14986,5826335,244218,7794 14989,8068180,893328,9444 14992,4642842,145536,8729 14996,1255538,507697,7505 14997,10138510,59446,9995 14998,10315581,517617,9638 15003,7617939,775742,10629 15006,9957503,594263,10013 15008,2621006,432858,7286 15012,5955235,761781,8914 15013,7079801,669361,9140 15015,1809253,325500,10593 15020,5454528,299785,6206 15021,4072146,129509,10272 15023,2762757,351747,10500 15027,8697826,161495,6690 15028,2666392,113527,8138 15031,6783402,663685,8057 15033,5333046,286691,6838 15037,2012164,714663,6405 15040,1910885,293403,7911 15044,6010077,331192,9657 15045,1863836,454256,6788 15047,1561683,290146,6421 15050,8620399,687216,10565 15053,1618649,808253,6410 15056,2079970,341283,6214 15059,6996827,563789,8722 15062,787870,684945,7450 15063,2180215,762916,9071 15068,2073851,465851,10060 15072,2292973,884933,5906 15076,4086897,815524,8956 15077,8066623,381611,10263 15080,4242248,396837,6795 15081,5603469,125963,6598 15083,7693731,575923,9895 15088,8846203,670415,6302 15092,5786664,89570,7018 15093,8942487,420753,10349 15095,10673310,404432,10659 ================================================ FILE: tidb/join/t/r2.tbl ================================================ 2,56746,1311922 6,819360,6450995 9,264752,5435660 10,479664,7937731 11,367646,5162612 13,392351,4908357 14,790354,5090785 19,212651,9591632 23,695363,7413765 28,5844,537429 33,392371,533839 35,379357,275268 39,734653,9627423 42,169629,8582061 43,811357,4079184 48,126749,7576913 52,552544,3907960 56,598402,6774762 61,511493,6290552 63,337239,6606506 66,242188,9708282 71,260840,593814 72,153979,5874379 74,640171,4560068 78,188440,9727502 80,817855,9640816 83,352112,1469641 86,659189,5818255 90,317479,3501286 91,760347,2918444 95,569090,4059747 99,748037,1583483 104,638448,3444568 107,818452,138430 108,622867,8360602 112,242362,9712644 116,94383,10487494 117,386836,9699935 121,355425,3370017 124,459909,6308809 128,696553,126419 129,330016,3819296 130,887470,8473102 135,868874,8395503 140,313290,1145681 145,205880,4896072 148,412400,3546008 150,204591,1528363 152,93828,5800937 153,328078,9848472 154,525489,553658 158,454484,858428 160,935895,10653753 163,178152,4208331 165,904938,1399688 170,26772,7341097 171,736115,7122489 174,621525,10304875 176,750609,8466043 178,802062,4724759 179,617046,7161797 182,865316,10190768 183,688537,10084219 187,513934,1169720 188,382896,4892266 193,182613,5599695 195,656663,7853459 198,392894,2049562 203,154726,6004072 205,129964,4887248 210,146349,3479584 215,727492,2560692 219,165749,7396026 222,67038,4832474 224,60368,5069485 228,380980,4780205 230,256973,7936548 233,94849,6192320 234,250318,2342531 237,69822,4810984 241,569696,6939270 242,518811,9932071 243,48611,579727 247,44541,6352844 251,630319,3203238 255,107149,8450768 259,158426,8679646 264,394330,10402778 266,719688,1941454 268,84957,2474030 272,453513,7417468 275,535836,3600363 277,381692,10007569 282,441002,7161771 287,379228,5096376 290,286999,1973878 291,54503,3731243 296,185947,3091639 300,44673,5233624 301,705416,3572630 303,528565,1778159 304,819393,9828039 305,924132,8045037 307,55527,7384958 309,11,4317116 314,917107,9386140 317,100801,9904659 321,512411,9791462 322,273192,8344430 327,469228,6142535 332,224823,3354118 333,358577,3600091 338,228646,75621 343,168482,748895 347,540142,9669507 351,737217,8037133 354,932438,9358162 357,523853,4308005 361,357194,10350764 366,795944,3502738 369,115723,486747 372,92671,8664162 374,88533,5408268 376,406885,7078730 381,224785,385269 385,657565,287152 387,619993,7005285 388,162374,3639903 389,818496,392192 391,481957,7640884 392,598126,1413647 393,408223,1833413 395,914556,7997213 398,35744,8171872 399,824882,3808860 403,890667,5491135 408,848232,3782325 413,117737,8585509 417,594768,2429487 418,104275,6749680 423,697665,2522460 428,298298,9763109 431,249141,2313861 433,644845,6292314 435,130249,261857 439,762133,10127407 444,788765,4972584 448,401272,2382718 449,575425,8097755 450,797385,6332325 454,231910,8453726 459,695912,5578588 464,62620,1549085 466,57819,8411815 469,22654,1051460 473,735719,962861 474,847180,9409388 478,903051,5680754 483,428210,5020726 488,871917,8560202 490,101951,277443 493,37222,6113795 494,937033,6022719 499,97824,2337726 503,538717,5034806 505,78130,5828404 509,58193,5365832 510,494489,769388 511,912655,48455 513,423796,9210477 515,48846,8097007 518,159894,8817858 521,849759,5668133 522,671047,2824432 524,278375,4987587 528,346649,9758363 533,73760,6436855 535,245904,1487076 539,604547,9098941 541,453486,8216184 544,314803,5755831 549,604968,5803110 552,744587,7313314 557,26673,949384 560,933388,9523773 565,311003,5238443 568,306551,1363300 573,389689,8525403 576,735741,4484512 577,317494,3238687 580,644396,1850340 583,199120,3788045 585,661888,871247 590,184914,8282207 594,548101,7992549 598,395060,9238513 602,649146,6613031 604,823957,9203794 605,406158,4069915 606,283623,9534927 607,380238,5263335 611,613332,3210680 616,783622,7531357 619,441620,10294650 620,848410,4549169 622,641713,8115384 623,53374,5198324 624,6423,8758410 625,221885,4930565 630,109808,8728071 632,366517,5652854 636,621541,4680127 639,486960,3254982 643,429151,5412838 648,165250,2377381 649,483697,1949181 651,691463,4449483 655,626932,3642169 658,682241,4430180 663,323587,2239577 666,346837,3839334 671,351170,2265647 672,763634,8371561 674,929429,5441905 677,584096,7064940 678,856170,480849 680,631825,9010680 685,552759,2550684 687,780714,3841412 692,502576,643523 697,532468,9767955 699,619906,3090233 701,754022,7193385 702,364370,9482526 706,264429,4424982 708,577033,1878910 712,514159,3905609 717,250323,297195 721,534229,2168509 724,452240,413678 725,156983,5806327 726,500297,920007 727,639429,10049865 729,745354,4605030 733,610763,10577429 738,259982,2677047 743,588287,3562 744,896079,4024909 749,180610,5745973 754,657886,8949723 757,101605,3786175 758,53372,5994585 762,283284,10011290 763,591425,151276 767,261845,228117 771,299373,808936 774,107998,8305614 779,319389,7606048 781,832556,9305018 786,800160,3375988 790,571831,4387891 792,793783,7275895 795,268208,2129444 798,798718,1205727 800,509190,8314559 802,440531,2891574 805,535444,3317470 807,345777,1764326 809,97914,8756717 814,596885,4146172 819,127893,3550733 820,750938,3836499 822,403110,3045548 823,508100,3347497 825,449763,1233289 828,26300,8593352 832,167568,428399 837,442881,5179665 842,899613,5544413 845,240262,5251045 849,118889,6073198 853,121412,5074874 854,5997,3658109 859,79983,7359697 862,589506,6247912 865,420942,8612884 866,402842,3010057 868,923109,7397044 870,871419,1491519 873,183316,7883031 876,869291,5173494 880,625843,3468829 884,887187,3669233 885,54740,9605597 888,413126,9777768 892,166085,10618042 894,644565,10087746 899,491499,1245297 902,558447,6546704 906,267010,4066025 910,192238,10353836 915,889388,543955 918,728866,7117407 922,2948,7429430 923,104678,5603336 926,931051,1866716 929,866209,9552731 934,386054,8201368 935,457611,9498560 940,821430,5681106 943,853319,333823 944,896834,1521671 945,235153,3728021 950,113960,10594116 951,450969,2720566 952,910905,1622848 956,340388,906490 957,159606,6980221 958,247134,8432932 961,913977,5092963 963,795112,3364136 966,309116,6774205 967,875585,8743383 970,578928,4260267 972,623420,7156553 976,285117,5972348 981,689942,8764431 983,595907,7589645 986,14524,4660891 989,829577,8593922 991,382465,5873201 992,776110,5373282 996,710827,9705715 997,636591,2681510 998,383107,3501737 1001,531079,2679195 1005,344451,6334643 1007,432145,3139985 1011,473313,363418 1015,297526,511654 1016,368447,627585 1021,144851,4962870 1024,122248,7038376 1025,346478,4265122 1028,301553,8303684 1032,379942,9414407 1035,771888,276774 1037,9267,897360 1038,371236,6333974 1040,381583,4712098 1041,114346,6855587 1046,739043,2564140 1051,730878,3406424 1052,216921,10384478 1055,293345,4105511 1060,245859,10535143 1062,119933,865516 1063,630018,10420847 1068,220002,7963811 1069,288314,4335622 1073,707164,8953928 1074,197365,8958893 1078,86372,9011743 1081,750267,6892520 1083,432120,3436597 1086,529219,4014817 1090,936116,3517759 1093,159283,4461330 1098,382984,1211753 1099,635524,6736244 1101,714795,1189953 1105,609150,2026203 1109,508123,9411841 1113,48688,10185145 1115,909035,288595 1116,392034,654065 1118,136562,3094440 1123,491777,5878300 1126,569598,3199157 1129,497494,3012517 1130,673612,1016194 1135,826985,2898655 1136,388551,5324130 1140,749018,1276600 1143,556140,2954921 1147,722899,9993761 1150,500855,4007634 1154,28755,8454908 1157,414915,10262559 1161,589316,4617709 1164,929124,7075970 1168,560865,2733633 1169,576537,5382995 1173,160356,9547985 1177,770730,1951088 1180,475443,8552057 1184,100868,6706848 1185,725174,3909041 1188,140364,5810909 1191,892335,4134639 1192,869157,1989859 1197,204758,7914012 1198,774652,6773136 1201,668377,4117783 1206,158266,3830281 1207,16208,5282081 1210,274262,8322412 1212,706429,5336839 1215,479826,3113124 1216,53755,2346803 1219,198977,9063813 1223,785910,4755052 1224,435852,1689321 1229,288679,5739707 1233,198140,9036477 1234,810756,8266515 1235,605118,4318152 1239,169241,4462878 1241,238840,7330487 1246,677804,8610776 1251,432088,8862136 1254,526428,3597637 1259,293820,1578837 1260,607015,4300286 1261,1909,6447969 1264,187066,4465212 1265,497064,8246038 1267,119645,223615 1271,144997,7654941 1273,913459,10397536 1275,59366,9674237 1279,382605,8803318 1280,497264,8927532 1282,884300,3607476 1287,167874,8198649 1290,850512,1572190 1291,805604,1036747 1293,26225,4328129 1294,189675,5310965 1297,416526,2107939 1299,658771,2109584 1303,846549,3598225 1308,145783,8258480 1311,537114,9004184 1312,485614,1164227 1316,861944,4286776 1317,65116,10272647 1320,911839,6707093 1324,218781,7475581 1325,13630,4484077 1328,80752,2894489 1331,172427,6780179 1334,80009,6269399 1338,153700,10579750 1342,157640,3625141 1347,750016,1798569 1350,23351,1107907 1352,44448,9365574 1355,756740,8380519 1358,389117,1292578 1362,637946,8561349 1363,346442,10648382 1364,295454,5892841 1368,46773,10186179 1371,526279,854925 1372,536184,1511104 1374,649098,5402582 1378,227109,2154337 1380,564043,9536792 1383,377163,2966231 1386,882666,7344616 1389,274970,3978771 1390,39194,7310586 1392,608861,10328146 1397,908330,1881997 1399,375544,7957836 1401,391674,7616020 1403,531688,1182773 1405,850092,1553772 1410,815111,2372230 1414,785197,6062130 1415,598693,6931507 1419,393345,3485159 1421,380543,6984419 1422,772035,7840655 1427,135578,7739073 1431,863914,3633567 1436,780182,4240928 1440,491157,6189838 1443,522179,735664 1446,205407,4631963 1448,104594,8715259 1453,491743,2293589 1456,426399,10182612 1460,110830,5690103 1462,285655,3564552 1464,623060,1876549 1466,427725,1493123 1470,732574,3160540 1471,700385,7070059 ================================================ FILE: tidb/mapreduce/.gitignore ================================================ .idea/ ================================================ FILE: tidb/mapreduce/Makefile ================================================ .PHONY: all all: test_example test_homework cleanup gendata test_example: go test -v -run=TestExampleURLTop test_homework: go test -v -run=TestURLTop cleanup: go test -v -run=TestCleanData gendata: go test -v -run=TestGenData ================================================ FILE: tidb/mapreduce/README.md ================================================ ## Introduction This is the Map-Reduce homework for PingCAP Talent Plan Online of week 2. There is a uncompleted Map-Reduce framework, you should complete it and use it to extract the 10 most frequent URLs from data files. ## Getting familiar with the source The simple Map-Reduce framework is defined in `mapreduce.go`. It is uncompleted and you should fill your code below comments `YOUR CODE HERE`. The map and reduce function are defined as same as MIT 6.824 lab 1. ``` type ReduceF func(key string, values []string) string type MapF func(filename string, contents string) []KeyValue ``` There is an example in `urltop10_example.go` which is used to extract the 10 most frequent URLs. After completing the framework, you can run this example by `make test_example`. And then please implement your own `MapF` and `ReduceF` in `urltop10.go` to accomplish this task. After filling your code, please use `make test_homework` to test. All data files will be generated at runtime, and you can use `make cleanup` to clean all test data. Please output URLs by lexicographical order and ensure that your result has the same format as test data so that you can pass all tests. Each test cases has **different data distribution** and you should take it into account. ## Requirements and rating principles * (40%) Performs better than `urltop10_example`. * (20%) Pass all test cases. * (30%) Have a document to describe your idea and record the process of performance optimization (both the framework and your own code) with `pprof`. * (10%) Have a good code style. NOTE: **go 1.12 is required** ## How to use Fill your code below comments `YOUR CODE HERE` in `mapreduce.go` to complete this framework. Implement your own `MapF` and `ReduceF` in `urltop10.go` and use `make test_homework` to test it. There is a builtin unit test defined in `urltop10_test.go`, however, you still can write your own unit tests. How to run example: ``` make test_example ``` How to test your implementation: ``` make test_homework ``` How to clean up all test data: ``` make cleanup ``` How to generate test data again: ``` make gendata ``` ================================================ FILE: tidb/mapreduce/casegen.go ================================================ package main import ( "fmt" "math/rand" "path" "sort" ) type DataSize int const ( KB = 1 << 10 MB = 1 << 20 GB = 1 << 30 ) func (d DataSize) String() string { if d < KB { return fmt.Sprintf("%dbyte", d) } else if d < MB { return fmt.Sprintf("%dKB", d/KB) } else if d < GB { return fmt.Sprintf("%dMB", d/MB) } return fmt.Sprintf("%dGB", d/GB) } // Case represents a test case. type Case struct { MapFiles []string // input files for map function ResultFile string // expected result } // CaseGenF represents test case generate function type CaseGenF func(dataFileDir string, totalDataSize, nMapFiles int) Case // AllCaseGenFs returns all CaseGenFs used to test. func AllCaseGenFs() []CaseGenF { var gs []CaseGenF gs = append(gs, genUniformCases()...) gs = append(gs, genPercentCases()...) gs = append(gs, CaseSingleURLPerFile) return gs } func genUniformCases() []CaseGenF { cardinalities := []int{1, 7, 200, 10000, 1000000} gs := make([]CaseGenF, 0, len(cardinalities)) for i := range cardinalities { card := cardinalities[i] gs = append(gs, func(dataFileDir string, totalDataSize, nMapFiles int) Case { if FileOrDirExist(dataFileDir) { files := make([]string, 0, nMapFiles) for i := 0; i < nMapFiles; i++ { fpath := path.Join(dataFileDir, fmt.Sprintf("inputMapFile%d", i)) files = append(files, fpath) } rpath := path.Join(dataFileDir, "result") return Case{ MapFiles: files, ResultFile: rpath, } } urls, avgLen := randomNURL(card) eachRecords := (totalDataSize / nMapFiles) / avgLen files := make([]string, 0, nMapFiles) urlCount := make(map[string]int, len(urls)) for i := 0; i < nMapFiles; i++ { fpath := path.Join(dataFileDir, fmt.Sprintf("inputMapFile%d", i)) files = append(files, fpath) f, buf := CreateFileAndBuf(fpath) for i := 0; i < eachRecords; i++ { str := urls[rand.Int()%len(urls)] urlCount[str]++ WriteToBuf(buf, str, "\n") } SafeClose(f, buf) } rpath := path.Join(dataFileDir, "result") genResult(rpath, urlCount) return Case{ MapFiles: files, ResultFile: rpath, } }) } return gs } func genPercentCases() []CaseGenF { ps := []struct { l int p []float64 }{ {11, []float64{0.9, 0.09, 0.009, 0.0009, 0.00009, 0.000009}}, {10000, []float64{0.9, 0.09, 0.009, 0.0009, 0.00009, 0.000009}}, {100000, []float64{0.9, 0.09, 0.009, 0.0009, 0.00009, 0.000009}}, {10000, []float64{0.5, 0.4}}, {10000, []float64{0.3, 0.3, 0.3}}, } gs := make([]CaseGenF, 0, len(ps)) for i := range ps { p := ps[i] gs = append(gs, func(dataFileDir string, totalDataSize, nMapFiles int) Case { if FileOrDirExist(dataFileDir) { files := make([]string, 0, nMapFiles) for i := 0; i < nMapFiles; i++ { fpath := path.Join(dataFileDir, fmt.Sprintf("inputMapFile%d", i)) files = append(files, fpath) } rpath := path.Join(dataFileDir, "result") return Case{ MapFiles: files, ResultFile: rpath, } } // make up percents list percents := make([]float64, 0, p.l) percents = append(percents, p.p...) var sum float64 for _, p := range p.p { sum += p } if sum > 1 || len(p.p) > p.l { panic("invalid prefix") } x := (1 - sum) / float64(p.l-len(p.p)) for i := 0; i < p.l-len(p.p); i++ { percents = append(percents, x) } // generate data urls, avgLen := randomNURL(len(percents)) eachRecords := (totalDataSize / nMapFiles) / avgLen files := make([]string, 0, nMapFiles) urlCount := make(map[string]int, len(urls)) accumulate := make([]float64, len(percents)+1) accumulate[0] = 0 for i := range percents { accumulate[i+1] = accumulate[i] + percents[i] } for i := 0; i < nMapFiles; i++ { fpath := path.Join(dataFileDir, fmt.Sprintf("inputMapFile%d", i)) files = append(files, fpath) f, buf := CreateFileAndBuf(fpath) for i := 0; i < eachRecords; i++ { x := rand.Float64() idx := sort.SearchFloat64s(accumulate, x) if idx != 0 { idx-- } str := urls[idx] urlCount[str]++ WriteToBuf(buf, str, "\n") } SafeClose(f, buf) } rpath := path.Join(dataFileDir, "result") genResult(rpath, urlCount) return Case{ MapFiles: files, ResultFile: rpath, } }) } return gs } // CaseSingleURLPerFile . func CaseSingleURLPerFile(dataFileDir string, totalDataSize, nMapFiles int) Case { if FileOrDirExist(dataFileDir) { files := make([]string, 0, nMapFiles) for i := 0; i < nMapFiles; i++ { fpath := path.Join(dataFileDir, fmt.Sprintf("inputMapFile%d", i)) files = append(files, fpath) } rpath := path.Join(dataFileDir, "result") return Case{ MapFiles: files, ResultFile: rpath, } } urls, avgLen := randomNURL(nMapFiles) eachRecords := (totalDataSize / nMapFiles) / avgLen files := make([]string, 0, nMapFiles) urlCount := make(map[string]int, len(urls)) for i := 0; i < nMapFiles; i++ { fpath := path.Join(dataFileDir, fmt.Sprintf("inputMapFile%d", i)) files = append(files, fpath) f, buf := CreateFileAndBuf(fpath) for j := 0; j < eachRecords; j++ { str := urls[i] urlCount[str]++ WriteToBuf(buf, str, "\n") } SafeClose(f, buf) } rpath := path.Join(dataFileDir, "result") genResult(rpath, urlCount) return Case{ MapFiles: files, ResultFile: rpath, } } func genResult(rpath string, urlCount map[string]int) { us, cs := TopN(urlCount, 10) f, buf := CreateFileAndBuf(rpath) for i := range us { fmt.Fprintf(buf, "%s: %d\n", us[i], cs[i]) } SafeClose(f, buf) } func randomNURL(n int) ([]string, int) { length := 0 urls := make([]string, 0, n) for i := 0; i < n; i++ { url := wrapLikeURL(fmt.Sprintf("%d", i)) length += len(url) urls = append(urls, url) } return urls, length / len(urls) } var urlPrefixes = []string{ "github.com/pingcap/tidb/issues", "github.com/pingcap/tidb/pull", "github.com/pingcap/tidb", } func wrapLikeURL(suffix string) string { return path.Join(urlPrefixes[rand.Intn(len(urlPrefixes))], suffix) } ================================================ FILE: tidb/mapreduce/go.mod ================================================ module talent go 1.12 ================================================ FILE: tidb/mapreduce/go.sum ================================================ github.com/pingcap/talent-plan v0.0.0-20190408125936-2f97dda786d6 h1:Kr1alXUfrJVBcLQb9tbrZGpInKkBhGLZsuMKNfesH1I= ================================================ FILE: tidb/mapreduce/mapreduce.go ================================================ package main import ( "bufio" "encoding/json" "hash/fnv" "io/ioutil" "log" "os" "path" "runtime" "strconv" "sync" ) // KeyValue is a type used to hold the key/value pairs passed to the map and reduce functions. type KeyValue struct { Key string Value string } // ReduceF function from MIT 6.824 LAB1 type ReduceF func(key string, values []string) string // MapF function from MIT 6.824 LAB1 type MapF func(filename string, contents string) []KeyValue // jobPhase indicates whether a task is scheduled as a map or reduce task. type jobPhase string const ( mapPhase jobPhase = "mapPhase" reducePhase = "reducePhase" ) type task struct { dataDir string jobName string mapFile string // only for map, the input file phase jobPhase // are we in mapPhase or reducePhase? taskNumber int // this task's index in the current phase nMap int // number of map tasks nReduce int // number of reduce tasks mapF MapF // map function used in this job reduceF ReduceF // reduce function used in this job wg sync.WaitGroup } // MRCluster represents a map-reduce cluster. type MRCluster struct { nWorkers int wg sync.WaitGroup taskCh chan *task exit chan struct{} } var singleton = &MRCluster{ nWorkers: runtime.NumCPU(), taskCh: make(chan *task), exit: make(chan struct{}), } func init() { singleton.Start() } // GetMRCluster returns a reference to a MRCluster. func GetMRCluster() *MRCluster { return singleton } // NWorkers returns how many workers there are in this cluster. func (c *MRCluster) NWorkers() int { return c.nWorkers } // Start starts this cluster. func (c *MRCluster) Start() { for i := 0; i < c.nWorkers; i++ { c.wg.Add(1) go c.worker() } } func (c *MRCluster) worker() { defer c.wg.Done() for { select { case t := <-c.taskCh: if t.phase == mapPhase { content, err := ioutil.ReadFile(t.mapFile) if err != nil { panic(err) } fs := make([]*os.File, t.nReduce) bs := make([]*bufio.Writer, t.nReduce) for i := range fs { rpath := reduceName(t.dataDir, t.jobName, t.taskNumber, i) fs[i], bs[i] = CreateFileAndBuf(rpath) } results := t.mapF(t.mapFile, string(content)) for _, kv := range results { enc := json.NewEncoder(bs[ihash(kv.Key)%t.nReduce]) if err := enc.Encode(&kv); err != nil { log.Fatalln(err) } } for i := range fs { SafeClose(fs[i], bs[i]) } } else { // YOUR CODE HERE :) // hint: don't encode results returned by ReduceF, and just output // them into the destination file directly so that users can get // results formatted as what they want. panic("YOUR CODE HERE") } t.wg.Done() case <-c.exit: return } } } // Shutdown shutdowns this cluster. func (c *MRCluster) Shutdown() { close(c.exit) c.wg.Wait() } // Submit submits a job to this cluster. func (c *MRCluster) Submit(jobName, dataDir string, mapF MapF, reduceF ReduceF, mapFiles []string, nReduce int) <-chan []string { notify := make(chan []string) go c.run(jobName, dataDir, mapF, reduceF, mapFiles, nReduce, notify) return notify } func (c *MRCluster) run(jobName, dataDir string, mapF MapF, reduceF ReduceF, mapFiles []string, nReduce int, notify chan<- []string) { // map phase nMap := len(mapFiles) tasks := make([]*task, 0, nMap) for i := 0; i < nMap; i++ { t := &task{ dataDir: dataDir, jobName: jobName, mapFile: mapFiles[i], phase: mapPhase, taskNumber: i, nReduce: nReduce, nMap: nMap, mapF: mapF, } t.wg.Add(1) tasks = append(tasks, t) go func() { c.taskCh <- t }() } for _, t := range tasks { t.wg.Wait() } // reduce phase // YOUR CODE HERE :D panic("YOUR CODE HERE") } func ihash(s string) int { h := fnv.New32a() h.Write([]byte(s)) return int(h.Sum32() & 0x7fffffff) } func reduceName(dataDir, jobName string, mapTask int, reduceTask int) string { return path.Join(dataDir, "mrtmp."+jobName+"-"+strconv.Itoa(mapTask)+"-"+strconv.Itoa(reduceTask)) } func mergeName(dataDir, jobName string, reduceTask int) string { return path.Join(dataDir, "mrtmp."+jobName+"-res-"+strconv.Itoa(reduceTask)) } ================================================ FILE: tidb/mapreduce/urltop10.go ================================================ package main // URLTop10 . func URLTop10(nWorkers int) RoundsArgs { // YOUR CODE HERE :) // And don't forget to document your idea. panic("YOUR CODE HERE") return nil } ================================================ FILE: tidb/mapreduce/urltop10_example.go ================================================ package main import ( "bytes" "fmt" "strconv" "strings" ) // ExampleURLTop10 generates RoundsArgs for getting the 10 most frequent URLs. // There are two rounds in this approach. // The first round will do url count. // The second will sort results generated in the first round and // get the 10 most frequent URLs. func ExampleURLTop10(nWorkers int) RoundsArgs { var args RoundsArgs // round 1: do url count args = append(args, RoundArgs{ MapFunc: ExampleURLCountMap, ReduceFunc: ExampleURLCountReduce, NReduce: nWorkers, }) // round 2: sort and get the 10 most frequent URLs args = append(args, RoundArgs{ MapFunc: ExampleURLTop10Map, ReduceFunc: ExampleURLTop10Reduce, NReduce: 1, }) return args } // ExampleURLCountMap is the map function in the first round func ExampleURLCountMap(filename string, contents string) []KeyValue { lines := strings.Split(contents, "\n") kvs := make([]KeyValue, 0, len(lines)) for _, l := range lines { l = strings.TrimSpace(l) if len(l) == 0 { continue } kvs = append(kvs, KeyValue{Key: l}) } return kvs } // ExampleURLCountReduce is the reduce function in the first round func ExampleURLCountReduce(key string, values []string) string { return fmt.Sprintf("%s %s\n", key, strconv.Itoa(len(values))) } // ExampleURLTop10Map is the map function in the second round func ExampleURLTop10Map(filename string, contents string) []KeyValue { lines := strings.Split(contents, "\n") kvs := make([]KeyValue, 0, len(lines)) for _, l := range lines { kvs = append(kvs, KeyValue{"", l}) } return kvs } // ExampleURLTop10Reduce is the reduce function in the second round func ExampleURLTop10Reduce(key string, values []string) string { cnts := make(map[string]int, len(values)) for _, v := range values { v := strings.TrimSpace(v) if len(v) == 0 { continue } tmp := strings.Split(v, " ") n, err := strconv.Atoi(tmp[1]) if err != nil { panic(err) } cnts[tmp[0]] = n } us, cs := TopN(cnts, 10) buf := new(bytes.Buffer) for i := range us { fmt.Fprintf(buf, "%s: %d\n", us[i], cs[i]) } return buf.String() } ================================================ FILE: tidb/mapreduce/urltop10_test.go ================================================ package main import ( "fmt" "log" "os" "path" "runtime" "testing" "time" ) func testDataScale() ([]DataSize, []int) { dataSize := []DataSize{1 * MB, 10 * MB, 100 * MB, 500 * MB, 1 * GB} nMapFiles := []int{5, 10, 20, 40, 60} return dataSize, nMapFiles } const ( dataDir = "/tmp/mr_homework" ) func dataPrefix(i int, ds DataSize, nMap int) string { return path.Join(dataDir, fmt.Sprintf("case%d-%s-%d", i, ds, nMap)) } func TestGenData(t *testing.T) { gens := AllCaseGenFs() dataSize, nMapFiles := testDataScale() for k := range dataSize { for i, gen := range gens { fmt.Printf("generate data file for cast%d, dataSize=%v, nMap=%v\n", i, dataSize[k], nMapFiles[k]) prefix := dataPrefix(i, dataSize[k], nMapFiles[k]) gen(prefix, int(dataSize[k]), nMapFiles[k]) } } } func TestCleanData(t *testing.T) { if err := os.RemoveAll(dataDir); err != nil { log.Fatal(err) } } func TestExampleURLTop(t *testing.T) { rounds := ExampleURLTop10(GetMRCluster().NWorkers()) testURLTop(t, rounds) } func TestURLTop(t *testing.T) { rounds := URLTop10(GetMRCluster().NWorkers()) testURLTop(t, rounds) } func testURLTop(t *testing.T, rounds RoundsArgs) { if len(rounds) == 0 { t.Fatalf("no rounds arguments, please finish your code") } mr := GetMRCluster() // run all cases gens := AllCaseGenFs() dataSize, nMapFiles := testDataScale() for k := range dataSize { for i, gen := range gens { // generate data prefix := dataPrefix(i, dataSize[k], nMapFiles[k]) c := gen(prefix, int(dataSize[k]), nMapFiles[k]) runtime.GC() // run map-reduce rounds begin := time.Now() inputFiles := c.MapFiles for idx, r := range rounds { jobName := fmt.Sprintf("Case%d-Round%d", i, idx) ch := mr.Submit(jobName, prefix, r.MapFunc, r.ReduceFunc, inputFiles, r.NReduce) inputFiles = <-ch } cost := time.Since(begin) // check result if len(inputFiles) != 1 { panic("the length of result file list should be 1") } result := inputFiles[0] if errMsg, ok := CheckFile(c.ResultFile, result); !ok { t.Fatalf("Case%d FAIL, dataSize=%v, nMapFiles=%v, cost=%v\n%v\n", i, dataSize[k], nMapFiles[k], cost, errMsg) } else { fmt.Printf("Case%d PASS, dataSize=%v, nMapFiles=%v, cost=%v\n", i, dataSize[k], nMapFiles[k], cost) } } } } ================================================ FILE: tidb/mapreduce/utils.go ================================================ package main import ( "bufio" "fmt" "io/ioutil" "os" "path" "sort" "strings" ) // RoundArgs contains arguments used in a map-reduce round. type RoundArgs struct { MapFunc MapF ReduceFunc ReduceF NReduce int } // RoundsArgs represents arguments used in multiple map-reduce rounds. type RoundsArgs []RoundArgs type urlCount struct { url string cnt int } // TopN returns topN urls in the urlCntMap. func TopN(urlCntMap map[string]int, n int) ([]string, []int) { ucs := make([]*urlCount, 0, len(urlCntMap)) for k, v := range urlCntMap { ucs = append(ucs, &urlCount{k, v}) } sort.Slice(ucs, func(i, j int) bool { if ucs[i].cnt == ucs[j].cnt { return ucs[i].url < ucs[j].url } return ucs[i].cnt > ucs[j].cnt }) urls := make([]string, 0, n) cnts := make([]int, 0, n) for i, u := range ucs { if i == n { break } urls = append(urls, u.url) cnts = append(cnts, u.cnt) } return urls, cnts } // CheckFile checks if these two files are same. func CheckFile(expected, got string) (string, bool) { c1, err := ioutil.ReadFile(expected) if err != nil { panic(err) } c2, err := ioutil.ReadFile(got) if err != nil { panic(err) } s1 := strings.TrimSpace(string(c1)) s2 := strings.TrimSpace(string(c2)) if s1 == s2 { return "", true } errMsg := fmt.Sprintf("expected:\n%s\n, but got:\n%s\n", c1, c2) return errMsg, false } // CreateFileAndBuf opens or creates a specific file for writing. func CreateFileAndBuf(fpath string) (*os.File, *bufio.Writer) { dir := path.Dir(fpath) os.MkdirAll(dir, 0777) f, err := os.OpenFile(fpath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) if err != nil { panic(err) } return f, bufio.NewWriterSize(f, 1<<20) } // OpenFileAndBuf opens a specific file for reading. func OpenFileAndBuf(fpath string) (*os.File, *bufio.Reader) { f, err := os.OpenFile(fpath, os.O_RDONLY, 0666) if err != nil { panic(err) } return f, bufio.NewReader(f) } // WriteToBuf write strs to this buffer. func WriteToBuf(buf *bufio.Writer, strs ...string) { for _, str := range strs { if _, err := buf.WriteString(str); err != nil { panic(err) } } } // SafeClose flushes this buffer and closes this file. func SafeClose(f *os.File, buf *bufio.Writer) { if buf != nil { if err := buf.Flush(); err != nil { panic(err) } } if err := f.Close(); err != nil { panic(err) } } // FileOrDirExist tests if this file or dir exist in a simple way. func FileOrDirExist(p string) bool { _, err := os.Stat(p) return err == nil } ================================================ FILE: tidb/mergesort/Makefile ================================================ .PHONY: all all: test bench test: go test bench: go test -bench Benchmark -run xx -count 5 -benchmem ================================================ FILE: tidb/mergesort/README.md ================================================ ## Introduction This is the Merge Sort home work for PingCAP Talent Plan Online of week 1. There are 16, 000, 000 int64 values stored in an unordered array. Please supplement the `MergeSort()` function defined in `mergesort.go` to sort this array. Requirements and rating principles: * (30%) Pass the unit test. * (20%) Performs better than `sort.Slice()`. * (40%) Have a document to describe your idea and record the process of performance optimization with `pprof`. * (10%) Have a good code style. NOTE: **go 1.12 is required** ## How to use Please supplement the `MergeSort()` function defined in `mergesort.go` to accomplish the home work. **NOTE**: 1. There is a builtin unit test defined in `mergesort_test.go`, however, you still can write your own unit tests. 2. There is a builtin benchmark test defined in `bench_test.go`, you should run this benchmark to ensure that your parallel merge sort is fast enough. How to test: ``` make test ``` How to benchmark: ``` make bench ``` ================================================ FILE: tidb/mergesort/bench_test.go ================================================ package main import ( "sort" "testing" ) func BenchmarkMergeSort(b *testing.B) { numElements := 16 << 20 src := make([]int64, numElements) original := make([]int64, numElements) prepare(original) b.ResetTimer() for i := 0; i < b.N; i++ { b.StopTimer() copy(src, original) b.StartTimer() MergeSort(src) } } func BenchmarkNormalSort(b *testing.B) { numElements := 16 << 20 src := make([]int64, numElements) original := make([]int64, numElements) prepare(original) b.ResetTimer() for i := 0; i < b.N; i++ { b.StopTimer() copy(src, original) b.StartTimer() sort.Slice(src, func(i, j int) bool { return src[i] < src[j] }) } } ================================================ FILE: tidb/mergesort/go.mod ================================================ module pingcap/talentplan/tidb/mergesort go 1.12 require github.com/pingcap/check v0.0.0-20190102082844-67f458068fc8 ================================================ FILE: tidb/mergesort/go.sum ================================================ github.com/pingcap/check v0.0.0-20190102082844-67f458068fc8 h1:USx2/E1bX46VG32FIw034Au6seQ2fY9NEILmNh/UlQg= github.com/pingcap/check v0.0.0-20190102082844-67f458068fc8/go.mod h1:B1+S9LNcuMyLH/4HMTViQOJevkGiik3wW2AN9zb2fNQ= ================================================ FILE: tidb/mergesort/mergesort.go ================================================ package main // MergeSort performs the merge sort algorithm. // Please supplement this function to accomplish the home work. func MergeSort(src []int64) { } ================================================ FILE: tidb/mergesort/mergesort_test.go ================================================ package main import ( "math/rand" "sort" "testing" "time" "github.com/pingcap/check" ) var _ = check.Suite(&sortTestSuite{}) func TestT(t *testing.T) { check.TestingT(t) } func prepare(src []int64) { rand.Seed(time.Now().Unix()) for i := range src { src[i] = rand.Int63() } } type sortTestSuite struct{} func (s *sortTestSuite) TestMergeSort(c *check.C) { lens := []int{1, 3, 5, 7, 11, 13, 17, 19, 23, 29, 1024, 1 << 13, 1 << 17, 1 << 19, 1 << 20} for i := range lens { src := make([]int64, lens[i]) expect := make([]int64, lens[i]) prepare(src) copy(expect, src) MergeSort(src) sort.Slice(expect, func(i, j int) bool { return expect[i] < expect[j] }) for i := 0; i < len(src); i++ { c.Assert(src[i], check.Equals, expect[i]) } } }