├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md ├── benchers ├── append_lat │ ├── Cargo.toml │ ├── get_ips.py │ ├── sequencer_throughput_v_latency_data__new.txt │ ├── src │ │ └── main.rs │ ├── start_clients.py │ └── start_servers.py ├── append_lat2 │ ├── Cargo.toml │ ├── get_ips.py │ ├── run_experiment.py │ └── src │ │ └── main.rs ├── backpointer │ ├── Cargo.toml │ ├── backpointer_latency.txt │ ├── get_ips.py │ ├── src │ │ └── main.rs │ ├── start_clients.py │ ├── start_servers.py │ └── t1 = [274777, 653553, 1398009, 2591003, 5067497, 1 ├── failure │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── fuzzy_log_throughput │ ├── Cargo.toml │ ├── dataset0 │ ├── dataset1 │ ├── dataset2 │ └── src │ │ └── main.rs ├── isolation │ ├── Cargo.toml │ ├── dataset0 │ ├── get_ips.py │ ├── src │ │ └── main.rs │ ├── start_clients.py │ └── start_servers.py ├── larger_ev │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── queue_bench │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── read_latency │ ├── Cargo.toml │ ├── get_ips.py │ ├── read_experiment.py │ ├── src │ │ └── main.rs │ ├── start_clients.py │ └── start_servers.py ├── replicated_failure │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── scaling │ ├── Cargo.toml │ ├── get_ips.py │ ├── run_experiment.py │ └── src │ │ └── main.rs ├── throughput │ ├── Cargo.toml │ └── src │ │ ├── main.rs │ │ ├── servers.rs │ │ └── workloads.rs └── trivial_server │ ├── .gitignore │ ├── Cargo.toml │ └── src │ └── main.rs ├── build.rs ├── cbindgen.toml ├── cbindgen_async_ext.toml ├── cleaner.sh ├── examples ├── c_linking │ ├── .gitignore │ ├── Cargo.toml │ ├── Makefile │ ├── Readme.md │ ├── fuzzy_log.h │ ├── src │ │ └── lib.rs │ └── start.c ├── c_multi_server │ ├── .gitignore │ ├── Makefile │ ├── Readme.md │ ├── server_config │ └── start.c ├── hello_c │ ├── .gitignore │ ├── Makefile │ ├── Readme.md │ └── main.c ├── hello_rust │ ├── Cargo.toml │ ├── Readme.md │ └── src │ │ └── main.rs ├── java_proxy │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── or_set │ ├── Cargo.toml │ └── src │ │ ├── getter.rs │ │ ├── main.rs │ │ ├── or_set.rs │ │ └── tester.rs ├── redblue │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── simple_map │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── tests.rs └── zookeeper │ ├── Cargo.toml │ ├── benches │ └── lib.rs │ ├── filter.py │ ├── get_ips.py │ ├── read_experiment.py │ ├── src │ ├── files.rs │ ├── lib.rs │ └── message.rs │ ├── tester │ ├── Cargo.toml │ ├── read_experiment.py │ ├── run_experiment.py │ └── src │ │ └── main.rs │ ├── traffic_gen │ ├── Cargo.toml │ ├── run_experiment.py │ └── src │ │ └── main.rs │ ├── view │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ ├── main.rs │ │ ├── msg.rs │ │ └── view.rs │ └── view2 │ ├── Cargo.toml │ └── src │ ├── lib.rs │ ├── main.rs │ ├── msg.rs │ ├── read_gen.rs │ └── view.rs ├── fuzzy_log_client ├── Cargo.toml └── src │ ├── colors.rs │ ├── fuzzy_log │ ├── log_handle.rs │ ├── mod.rs │ ├── per_color.rs │ └── range_tree.rs │ ├── lib.rs │ ├── replicator.rs │ └── store.rs ├── fuzzy_log_packets ├── Cargo.toml └── src │ ├── buffer.rs │ ├── buffer2.rs │ ├── double_buffer.rs │ ├── lib.rs │ └── storeables.rs ├── fuzzy_log_server ├── Cargo.toml └── src │ ├── byte_trie.rs │ ├── lib.rs │ ├── ordering_thread.rs │ ├── shared_slice.rs │ ├── skeens.rs │ ├── spmc.rs │ ├── spsc.rs │ ├── tcp │ ├── buffer_stream.rs │ ├── mod.rs │ ├── per_socket.rs │ ├── socket_negotiate.rs │ └── worker.rs │ ├── tests.rs │ ├── trie.rs │ ├── trivial_eq_arc.rs │ ├── udp.rs │ └── worker_thread.rs ├── fuzzy_log_util ├── Cargo.toml └── src │ ├── counter_macro.rs │ ├── hash.rs │ ├── hash_deque_map.rs │ ├── lib.rs │ ├── range_tree.rs │ ├── socket_addr.rs │ ├── tree_deque_map.rs │ └── vec_deque_map.rs ├── fuzzy_views ├── bloom │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── color_alloc │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── counter │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── counter2 │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── counter_err │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── lat_v_num_events │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── micropayments │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── ml │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── pre_v_post │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── pre_v_post_s │ ├── Cargo.toml │ └── src │ │ └── main.rs └── view_builder │ ├── Cargo.toml │ └── src │ └── lib.rs ├── fuzzylog.h ├── fuzzylog_async_ext.h ├── get_ips.py ├── packet-macro2 ├── .gitignore ├── Cargo.toml ├── packet-macro-impl │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── parser.rs └── src │ └── lib.rs ├── reactor ├── Cargo.toml └── src │ └── lib.rs ├── scripts ├── README.md ├── example_server_config ├── mirror_on_servers.py ├── mirror_on_servers.sh └── start_servers.sh ├── servers ├── tcp_server │ ├── .gitignore │ ├── Cargo.toml │ ├── Readme.md │ └── src │ │ └── main.rs └── tokio_server │ ├── .gitignore │ ├── Cargo.toml │ ├── Readme.md │ └── src │ └── main.rs ├── src ├── lib.rs ├── replication_tests.rs └── tests.rs └── tokio_server ├── Cargo.toml └── src ├── batch_read_buffer.rs ├── buf_writer.rs ├── buffer_stream.rs ├── doorbell.rs ├── lib.rs ├── read_buffer.rs ├── vec_stream.rs └── worker.rs /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | *.rlib 4 | *.a 5 | *.o 6 | out 7 | *.pyc 8 | 9 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fuzzy_log" 3 | version = "0.1.0" 4 | authors = ["J "] 5 | build = "build.rs" 6 | 7 | [lib] 8 | crate-type = ["lib", "staticlib"] 9 | 10 | [build-dependencies] 11 | cbindgen = "0.6.2" 12 | 13 | [dependencies] 14 | byteorder = "1" 15 | fuzzy_log_packets = {path = "./fuzzy_log_packets"} 16 | fuzzy_log_util = {path = "./fuzzy_log_util"} 17 | fuzzy_log_client = {path = "./fuzzy_log_client"} 18 | fuzzy_log_server = {path = "./fuzzy_log_server"} 19 | reactor = {path = "./reactor"} 20 | # tokio_server = {path = "./tokio_server"} 21 | libc = "0.2" 22 | log = "0.3" 23 | toml = "0.2" 24 | mio = "0.6.6" 25 | env_logger = "0.3" 26 | 27 | [features] 28 | no_trace = ["log/max_level_info"] 29 | print_stats = ["fuzzy_log_client/print_stats", "fuzzy_log_server/print_stats"] 30 | debug_no_drop = [] 31 | 32 | [profile.dev] 33 | panic = 'abort' 34 | 35 | [profile.release] 36 | opt-level = 3 37 | debug = false 38 | rpath = false 39 | debug-assertions = false 40 | panic = 'abort' 41 | 42 | [workspace] 43 | exclude = ["servers/", "examples", "clients", "benchers", "fuzzy_views", "tokio_server", 44 | "fuzzy_log.h", "fuzzylog_async_ext.h"] 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, Joshua Lockerman 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | _This work is funded by [NSF grant 1637385](https://nsf.gov/awardsearch/showAward?AWD_ID=1637385)_. Any opinions, findings, and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the National Science Foundation. 2 | 3 | 4 | # FuzzyLog 5 | 6 | This repository contains the unified code for the clients and servers for the FuzzyLog project; 7 | an experiment in partially ordered SMR. 8 | A [companion repository](https://github.com/JLockerman/FuzzyLog-apps) contains the remaining benchmark code. 9 | 10 | ## C Bindings 11 | 12 | C bindings and documentation are currently located in [`fuzzylog.h`](fuzzylog.h). 13 | A helloworld using them can be found in [examples/hello_c](examples/hello_c) 14 | 15 | ## To Build 16 | Download and install [rust](https://www.rust-lang.org) (easiest way is `curl https://sh.rustup.rs -sSf | sh`). 17 | Clone this repository. 18 | To run local tests 19 | 20 | cargo test 21 | 22 | **NOTE:** The first build will be much slower than subsequent ones 23 | as it needs to download dependencies. 24 | **NOTE:** Due to the very large number of sockets the test suite opens, running 25 | the entire test sweet concurrently often causes tests to fail with 26 | `Too many open files`. To fix this either run in single threaded mode 27 | (`RUST_TEST_THREADS=1 cargo test`) or run only a subset of the test suite. 28 | 29 | ## Servers 30 | 31 | A CLI binding for starting FuzzyLog servers can be found in [servers/tcp_server](servers/tcp_server). 32 | 33 | ## Directory Outline 34 | - [src/tests](src) the FuzzyLog regression tests. 35 | - [examples](examples) sample code which uses the client library to perform vaious tasks, of note are: 36 | - [hello_c](examples/hello_c) a C helloworld example. 37 | - [hello_rust](examples/hello_rust) the corresponding rust example. 38 | - [servers/tcp_server](servers/tcp_server) a TCP based fuzzy log sever. 39 | - [clients](clients) various DPDK based clients for use in testing (obsolescent). 40 | - [fuzzy_log_server](fuzzy_log_server) the fuzzy log server implementation library. 41 | - [fuzzy_log_client](fuzzy_log_client) the fuzzy log client implementation library. 42 | -------------------------------------------------------------------------------- /benchers/append_lat/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lat_v_even" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | crossbeam = "0.2.10" 8 | env_logger = "0.3" 9 | fuzzy_log_client = {path = "../../fuzzy_log_client"} 10 | fuzzy_log_util = {path = "../../fuzzy_log_util"} 11 | log = "0.3" 12 | mio = "0.6.6" 13 | structopt = "0.0.5" 14 | structopt-derive = "0.0.5" 15 | -------------------------------------------------------------------------------- /benchers/append_lat/get_ips.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | import boto3 3 | 4 | ec2client = boto3.client('ec2') 5 | response = ec2client.describe_instances() 6 | public_dns = [] 7 | private_ip = [] 8 | clients = [] 9 | servers = [] 10 | for reservation in response["Reservations"]: 11 | for instance in reservation["Instances"]: 12 | if instance[u'PublicDnsName'] != "": 13 | public_dns.append(instance[u'PublicDnsName']) 14 | private_ip.append(instance[u'PrivateIpAddress']) 15 | 16 | num_instances = len(private_ip) 17 | print(num_instances) 18 | num_clients = 1 19 | 20 | print(public_dns) 21 | print(len(public_dns)) 22 | print("") 23 | print("") 24 | print("Clients") 25 | print(public_dns[0:num_clients]) 26 | print("") 27 | print("Servers") 28 | print(public_dns[num_clients:]) 29 | print(private_ip[num_clients:]) 30 | print("") 31 | print("") 32 | print("Client Hosts") 33 | server_ips = "" 34 | for i in range(0, len(private_ip[num_clients:-1]), 2): 35 | server_ips = server_ips + private_ip[num_clients + i] + ":13289#" + private_ip[num_clients + i + 1] + ":13289^" 36 | print(server_ips) 37 | client_hosts = "" 38 | for client in public_dns[0:num_clients]: 39 | client_hosts = client_hosts + client + "," 40 | print(client_hosts) 41 | 42 | -------------------------------------------------------------------------------- /benchers/append_lat/start_clients.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | 3 | import subprocess 4 | import sys 5 | 6 | server_ips = '172.31.5.104:13289#172.31.14.200:13289^172.31.6.234:13289#172.31.3.204:13289' 7 | sequncer_ip = '172.31.9.12:13289' 8 | hostname = 'ec2-54-144-206-162.compute-1.amazonaws.com' 9 | 10 | command = 'mirror:cd ./benchers/append_lat/ && cargo run --release -- ' + server_ips + ' ' + sequncer_ip 11 | 12 | p1 = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", hostname, "mirror:rustup install 1.19.0 && rustup override set 1.19.0", command]) 13 | 14 | p1.wait() 15 | -------------------------------------------------------------------------------- /benchers/append_lat/start_servers.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | 3 | import subprocess 4 | import sys 5 | 6 | server_dns = ['ec2-34-207-252-255.compute-1.amazonaws.com', 'ec2-107-23-178-46.compute-1.amazonaws.com', 'ec2-34-235-87-54.compute-1.amazonaws.com', 'ec2-54-198-98-220.compute-1.amazonaws.com'] 7 | server_ips = ['172.31.5.104', '172.31.14.200', '172.31.6.234', '172.31.3.204'] 8 | sequencer = 'ec2-34-235-154-206.compute-1.amazonaws.com' 9 | seq_ip = '172.31.9.12' 10 | procs = [] 11 | 12 | # server_dns = ['ec2-52-72-66-109.compute-1.amazonaws.com', 'ec2-34-227-206-53.compute-1.amazonaws.com', 'ec2-34-229-205-4.compute-1.amazonaws.com', 'ec2-54-208-101-237.compute-1.amazonaws.com'] 13 | # server_ips = ['172.31.5.104', '172.31.14.200', '172.31.6.234', '172.31.3.204'] 14 | 15 | hostnames = "" 16 | ips = "" 17 | for i in range(0, len(server_dns)-2, 2): 18 | hostnames += server_dns[i] + "," + server_dns[i+1] + "," 19 | ips += server_ips[i] + "#" + server_ips[i+1] + "^" 20 | 21 | hostnames += server_dns[len(server_dns)-2] + "," + server_dns[len(server_dns)-1] 22 | ips += server_ips[len(server_dns)-2] + "#" + server_ips[len(server_dns)-1] 23 | 24 | command = "run_chain:chain_hosts=" + ips + ",nt=t" 25 | seq_command = "run_chain:chain_hosts=" + seq_ip + ",nt=t" 26 | print(command) 27 | p0 = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", hostnames, "mirror:rustup install 1.19.0 && rustup override set 1.19.0", command]) 28 | p1 = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", sequencer, "mirror:rustup install 1.19.0 && rustup override set 1.19.0", seq_command]) 29 | p0.wait() 30 | p1.wait() 31 | -------------------------------------------------------------------------------- /benchers/append_lat2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lat_v_even" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | crossbeam = "0.2.10" 8 | env_logger = "0.3" 9 | fuzzy_log_client = {path = "../../fuzzy_log_client"} 10 | fuzzy_log_util = {path = "../../fuzzy_log_util"} 11 | log = "0.3" 12 | mio = "0.6.6" 13 | structopt = "0.0.5" 14 | structopt-derive = "0.0.5" 15 | -------------------------------------------------------------------------------- /benchers/append_lat2/get_ips.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | import boto3 3 | 4 | ec2client = boto3.client('ec2') 5 | response = ec2client.describe_instances() 6 | public_dns = [] 7 | private_ip = [] 8 | clients = [] 9 | servers = [] 10 | for reservation in response["Reservations"]: 11 | for instance in reservation["Instances"]: 12 | if instance[u'PublicDnsName'] != "": 13 | public_dns.append(instance[u'PublicDnsName']) 14 | private_ip.append(instance[u'PrivateIpAddress']) 15 | 16 | num_instances = len(private_ip) 17 | print(num_instances) 18 | num_clients = 1 19 | 20 | print(public_dns) 21 | print(len(public_dns)) 22 | print("") 23 | print("") 24 | print("Clients") 25 | print(public_dns[0:num_clients]) 26 | print("") 27 | print("Servers") 28 | print(public_dns[num_clients:]) 29 | print(private_ip[num_clients:]) 30 | print("") 31 | print("") 32 | print("Client Hosts") 33 | server_ips = "" 34 | for i in range(0, len(private_ip[num_clients:-1]), 2): 35 | server_ips = server_ips + private_ip[num_clients + i] + ":13289#" + private_ip[num_clients + i + 1] + ":13289^" 36 | print(server_ips) 37 | client_hosts = "" 38 | for client in public_dns[0:num_clients]: 39 | client_hosts = client_hosts + client + "," 40 | print(client_hosts) 41 | 42 | -------------------------------------------------------------------------------- /benchers/append_lat2/run_experiment.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | 3 | import os 4 | import subprocess 5 | import sys 6 | import time 7 | 8 | server_ip = '172.31.5.245:13289#172.31.3.165:13289' 9 | # server_ip = '172.31.5.245:13289' 10 | 11 | server_ips = [ 12 | '', 13 | '172.31.5.245:13289', 14 | '172.31.5.245:13289#172.31.3.165:13289', 15 | '172.31.5.245:13289#172.31.3.165:13289', 16 | ] 17 | 18 | client_hostnames = ['ec2-54-91-87-24.compute-1.amazonaws.com', 'ec2-34-227-191-225.compute-1.amazonaws.com', 'ec2-54-208-118-55.compute-1.amazonaws.com', 'ec2-18-232-136-244.compute-1.amazonaws.com', 'ec2-52-23-169-156.compute-1.amazonaws.com', 'ec2-107-20-27-163.compute-1.amazonaws.com', 'ec2-54-198-222-245.compute-1.amazonaws.com', 'ec2-18-204-228-102.compute-1.amazonaws.com', 'ec2-54-172-173-203.compute-1.amazonaws.com', 'ec2-34-233-121-116.compute-1.amazonaws.com', 'ec2-34-224-213-245.compute-1.amazonaws.com', 'ec2-54-89-137-73.compute-1.amazonaws.com', 'ec2-54-208-183-23.compute-1.amazonaws.com', 'ec2-34-224-212-223.compute-1.amazonaws.com'] 19 | 20 | servers = ['ec2-52-55-100-37.compute-1.amazonaws.com', 'ec2-52-90-95-137.compute-1.amazonaws.com', 'ec2-34-224-39-39.compute-1.amazonaws.com'] 21 | servers = [ 22 | '', 23 | 'ec2-52-55-100-37.compute-1.amazonaws.com', 24 | 'ec2-52-55-100-37.compute-1.amazonaws.com,ec2-34-224-39-39.compute-1.amazonaws.com', 25 | 'ec2-52-55-100-37.compute-1.amazonaws.com,ec2-52-90-95-137.compute-1.amazonaws.com,ec2-34-224-39-39.compute-1.amazonaws.com', 26 | ] 27 | # server_hostnames = 'ec2-52-55-100-37.compute-1.amazonaws.com,ec2-34-224-39-39.compute-1.amazonaws.com' 28 | # server_hostnames = 'ec2-34-224-39-39.compute-1.amazonaws.com' 29 | 30 | ips = [ 31 | '', 32 | '172.31.5.245', 33 | '172.31.5.245#172.31.3.165', 34 | '172.31.5.245#172.31.0.84#172.31.3.165' 35 | ] 36 | 37 | num_servers = 1 38 | 39 | os.chdir('../..') 40 | 41 | command = "run_chain:chain_hosts=" + ips[num_servers] + ",nt=t" 42 | print(command) 43 | p0 = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", servers[num_servers], 44 | command]) 45 | 46 | time.sleep(2) 47 | 48 | command = 'mirror:pkill lat_v_even; cd benchers/append_lat2/ && RUST_BACKTRACE\=short cargo run --release -- ' + server_ips[num_servers] 49 | p1 = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", client_hostnames[0], 50 | command]) 51 | 52 | p1.wait() 53 | 54 | p0.kill() 55 | 56 | print("") 57 | print("> ") 58 | print("========================================") 59 | print("> ----------------------------------------") 60 | print("========================================") 61 | print("> ") 62 | print("") 63 | sys.stdout.flush() 64 | 65 | kill_hoststring = servers[0] 66 | for name in servers[1:len(servers)]: 67 | kill_hoststring += "," + name 68 | 69 | p0 = subprocess.Popen(["fab", "-f", "./mirror_on_servers.py", "-H", kill_hoststring, "kill_server"]) 70 | -------------------------------------------------------------------------------- /benchers/backpointer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "back" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | crossbeam = "0.2.10" 8 | env_logger = "0.3" 9 | fuzzy_log_client = {path = "../../fuzzy_log_client"} 10 | log = "0.3" 11 | mio = "0.6.6" 12 | structopt = "0.0.5" 13 | structopt-derive = "0.0.5" 14 | -------------------------------------------------------------------------------- /benchers/backpointer/backpointer_latency.txt: -------------------------------------------------------------------------------- 1 | 2 | #elapsed Duration { secs: 567, nanos: 860557800 } 3 | num_appends = [1, 4, 10, 20, 40, 80, 160] 4 | t1 = [271623, 658478, 1362838, 2548240, 4982693, 9810440, 19752026] 5 | t4 = [273364, 252747, 476687, 711941, 1207377, 2408472, 4862822] 6 | t10 = [281215, 250638, 264131, 403338, 655413, 1207597, 2333962] 7 | avg_regular_latencies = [156576, 148465, 171192, 204823, 235646, 316640, 453450] 8 | 9 | ======================================= 10 | ======================================= 11 | ======================================= 12 | ======================================= 13 | 14 | #Args { servers: ServerAddrs([V4(172.31.15.138:13289), V4(172.31.4.131:13289)]), num_rounds: 10000 } 15 | t1: 1 274777ns 16 | t4: 1 272015ns 17 | t10: 1 271750ns 18 | r: 1 155251ns 19 | t1: 4 653553ns 20 | t4: 4 301615ns 21 | t10: 4 297641ns 22 | r: 4 146127ns 23 | t1: 10 1398009ns 24 | t4: 10 505195ns 25 | t10: 10 294681ns 26 | r: 10 186132ns 27 | t1: 20 2591003ns 28 | t4: 20 739090ns 29 | t10: 20 417361ns 30 | r: 20 223363ns 31 | t1: 40 5067497ns 32 | t4: 40 1245306ns 33 | t10: 40 751101ns 34 | r: 40 259871ns 35 | t1: 80 10088297ns 36 | t4: 80 2465846ns 37 | t10: 80 1251402ns 38 | r: 80 348993ns 39 | t1: 160 19902211ns 40 | t4: 160 4924758ns 41 | t10: 160 2319455ns 42 | r: 160 462078ns 43 | #elapsed Duration { secs: 579, nanos: 341479821 } 44 | num_appends = [1, 4, 10, 20, 40, 80, 160] 45 | t1 = [274777, 653553, 1398009, 2591003, 5067497, 10088297, 19902211] 46 | t4 = [272015, 301615, 505195, 739090, 1245306, 2465846, 4924758] 47 | t10 = [271750, 297641, 294681, 417361, 751101, 1251402, 2319455] 48 | avg_regular_latencies = [155251, 146127, 186132, 223363, 259871, 348993, 462078] 49 | 50 | ======================================= 51 | ======================================= 52 | ======================================= 53 | ======================================= 54 | 55 | import matplotlib.pyplot as plt 56 | from matplotlib.backends.backend_pdf import PdfPages 57 | 58 | t1 = [271623, 658478, 1362838, 2548240, 4982693, 9810440, 19752026] 59 | t1 = map(lambda x: x/1000, t1) 60 | 61 | t4 = [273364, 252747, 476687, 711941, 1207377, 2408472, 4862822] 62 | t4 = map(lambda x: x/1000, t4) 63 | 64 | t10 = [281215, 250638, 264131, 403338, 655413, 1207597, 2333962] 65 | t10 = map(lambda x: x/1000, t10) 66 | 67 | avg_regular_latencies = [156576, 148465, 171192, 204823, 235646, 316640, 453450] 68 | avg_regular_latencies = map(lambda x: x/1000, avg_regular_latencies) 69 | 70 | x_tics = [1, 10, 20, 40, 80, 160] 71 | 72 | plt.figure(num=None, figsize=(6, 3), dpi=80, facecolor='w', edgecolor='k') 73 | #plt.plot(t1, marker="h", linestyle="-", color='lightblue') 74 | plt.plot(t4, marker="o", linestyle="-", color='darkblue') 75 | plt.plot(t10, marker="D", linestyle="-", color='blue') 76 | plt.plot(avg_regular_latencies, marker="x", linestyle="--", color='darkred') 77 | #plt.yscale('log') 78 | plt.xticks([0, 1, 2, 3, 4, 5], x_tics) 79 | plt.ylabel("Latency (microseconds)") 80 | plt.xlabel("Events Fetched") 81 | #plt.legend(["1 backpointer", "4 backpointers", "10 backpointer", "direct"], loc=2) 82 | plt.legend(["4 backpointers", "10 backpointer", "direct"], loc=2) 83 | pp = PdfPages('a.pdf') 84 | pp.savefig(bbox_inches='tight') 85 | pp.close() 86 | plt.show() 87 | -------------------------------------------------------------------------------- /benchers/backpointer/get_ips.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | import boto3 3 | 4 | ec2client = boto3.client('ec2') 5 | response = ec2client.describe_instances() 6 | public_dns = [] 7 | private_ip = [] 8 | clients = [] 9 | servers = [] 10 | for reservation in response["Reservations"]: 11 | for instance in reservation["Instances"]: 12 | if instance[u'PublicDnsName'] != "": 13 | public_dns.append(instance[u'PublicDnsName']) 14 | private_ip.append(instance[u'PrivateIpAddress']) 15 | 16 | num_instances = len(private_ip) 17 | print(num_instances) 18 | num_clients = 1 19 | 20 | print(public_dns) 21 | print(len(public_dns)) 22 | print("") 23 | print("") 24 | print("Clients") 25 | print(public_dns[0:num_clients]) 26 | print("") 27 | print("Servers") 28 | print(public_dns[num_clients:]) 29 | print(private_ip[num_clients:]) 30 | print("") 31 | print("") 32 | print("Client Hosts") 33 | server_ips = "" 34 | for i in range(0, len(private_ip[num_clients:]), 2): 35 | server_ips = server_ips + private_ip[num_clients + i] + ":13289^" + private_ip[num_clients + i + 1] + ":13289" 36 | print(server_ips) 37 | client_hosts = "" 38 | for client in public_dns[0:num_clients]: 39 | client_hosts = client_hosts + client + "," 40 | print(client_hosts) 41 | 42 | -------------------------------------------------------------------------------- /benchers/backpointer/start_clients.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | 3 | import subprocess 4 | import sys 5 | 6 | server_ips = '172.31.15.138:13289^172.31.4.131:13289' 7 | hostname = 'ec2-54-86-154-231.compute-1.amazonaws.com' 8 | 9 | command = 'mirror:cd ./benchers/backpointer/ && cargo run --release -- ' + server_ips 10 | 11 | p1 = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", hostname, "mirror:pkill back; rustup install 1.19.0 && rustup override set 1.19.0", command]) 12 | 13 | p1.wait() 14 | -------------------------------------------------------------------------------- /benchers/backpointer/start_servers.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | 3 | import subprocess 4 | import sys 5 | 6 | server_dns = ['ec2-107-20-87-53.compute-1.amazonaws.com', 'ec2-54-162-154-10.compute-1.amazonaws.com'] 7 | server_ips = ['172.31.15.138', '172.31.4.131'] 8 | procs = [] 9 | 10 | hostnames = "" 11 | ips = "" 12 | 13 | hostnames += server_dns[0] + "," + server_dns[1] 14 | ips += server_ips[0] + "^" + server_ips[1] 15 | 16 | command = "run_chain:chain_hosts=" + ips + ",nt=t" 17 | print(command) 18 | p0 = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", hostnames, "mirror:rustup install 1.19.0 && rustup override set 1.19.0", command]) 19 | 20 | p0.wait() 21 | -------------------------------------------------------------------------------- /benchers/backpointer/t1 = [274777, 653553, 1398009, 2591003, 5067497, 1: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | from matplotlib.backends.backend_pdf import PdfPages 3 | 4 | t1 = [274777, 653553, 1398009, 2591003, 5067497, 10088297, 19902211] 5 | t1_thorughput = map(lambda x: 1000000000/x, t1) 6 | 7 | t4 = [272015, 301615, 505195, 739090, 1245306, 2465846, 4924758] 8 | t4_thorughput = map(lambda x: 1000000000/x, t4) 9 | 10 | t10 = [271750, 297641, 294681, 417361, 751101, 1251402, 2319455] 11 | t10_thorughput = map(lambda x: 1000000000/x, t10) 12 | 13 | avg_regular_latencies = [155251, 146127, 186132, 223363, 259871, 348993, 462078] 14 | avg_regular_thorughput = map(lambda x: 1000000000/x, avg_regular_latencies) 15 | 16 | x_tics = [1, 10, 20, 40, 80, 160] 17 | 18 | print(t1_thorughput) 19 | print(t4_thorughput) 20 | print(t10_thorughput) 21 | print(avg_regular_thorughput) 22 | 23 | plt.figure(num=None, figsize=(6, 3), dpi=80, facecolor='w', edgecolor='k') 24 | #plt.plot(t1_thorughput, marker="h", linestyle="-", color='lightblue') 25 | plt.plot(t4_thorughput, marker="o", linestyle="-", color='darkblue') 26 | plt.plot(t10_thorughput, marker="D", linestyle="-", color='blue') 27 | plt.plot(avg_regular_thorughput, avg_regular_latencies, marker="x", linestyle="--", color='darkred') 28 | plt.xticks([0, 1, 2, 3, 4, 5], x_tics) 29 | #plt.yscale('log') 30 | #plt.ylabel("Latency (microseconds)") 31 | plt.ylabel("Hz") 32 | #plt.legend(["1 backpointer", "4 backpointers", "10 backpointer", "direct"], loc=2) 33 | plt.legend(["4 backpointers", "10 backpointer", "direct"], loc=2) 34 | #pp = PdfPages('a.pdf') 35 | #pp.savefig(bbox_inches='tight') 36 | #pp.close() 37 | plt.show() 38 | 39 | -------------------------------------------------------------------------------- /benchers/failure/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "failure" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | env_logger = "0.3" 8 | fuzzy_log = {path = "../.."} 9 | mio = "0.6.6" 10 | -------------------------------------------------------------------------------- /benchers/fuzzy_log_throughput/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fuzzy_log_throughput" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | crossbeam = "0.2.10" 8 | env_logger = "0.3" 9 | fuzzy_log_client = {path = "../../fuzzy_log_client"} 10 | log = "0.3" 11 | rand = "0.3" 12 | structopt = "0.0.5" 13 | structopt-derive = "0.0.5" 14 | 15 | [profile.release] 16 | opt-level = 3 17 | #debug = true 18 | debug = false 19 | rpath = false 20 | lto = false 21 | debug-assertions = false 22 | codegen-units = 1 23 | panic = 'abort' 24 | -------------------------------------------------------------------------------- /benchers/fuzzy_log_throughput/dataset0: -------------------------------------------------------------------------------- 1 | 2 | uniform random 3 | 4 | =======================================1 5 | 6 | 4188166 7 | 8 | =======================================2 9 | 10 | 327334 11 | 12 | =======================================3 13 | 14 | 395400 15 | 16 | =======================================4 17 | 18 | 359750 19 | 20 | =======================================5 21 | 22 | 194330 23 | 24 | ======================================= 25 | ======================================= 26 | ======================================= 27 | ======================================= 28 | 29 | split 30 | 31 | =======================================1 32 | 33 | --------------------------------------- 34 | 208800+ 221460+ 210961+ 246985+ 250354+ 231975+ 202425+ 216225+ 242475+ 240375 35 | = 2272035 36 | 37 | --------------------------------------- 38 | 234748+ 232875+ 214933+ 236382+ 227175+ 240750+ 233604+ 250127+ 233025+ 211275 39 | 40 | =2314894 41 | 42 | --------------------------------------- 43 | 239383+ 242625+ 244200+ 252600+ 246375+ 474236+ 247480+ 240225+ 242508+ 425086 44 | 45 | =2854718 46 | 47 | --------------------------------------- 48 | 49 | 2480549 50 | 51 | =======================================2 52 | 72325 + 88131 + 72488 + 249225 + 583687 + 72119 + 88370 + 72045 + 89966 + 90100 53 | = 1478456 54 | 55 | --------------------------------------- 56 | 81699 + 81634 + 83815 + 82701 + 83504 + 231675 + 238050 + 82618 + 84286 + 81439 57 | =1131421 58 | 59 | --------------------------------------- 60 | 70164 + 56125 + 55310 + 55956 + 55380 + 228958 + 70398 + 232178 + 70294 + 70439 61 | =965202 62 | 63 | --------------------------------------- 64 | 65 | 1191693 66 | 67 | =======================================3 68 | 48487 + 86316 + 51503 + 83917 + 51539 + 50059 + 48466 + 84301 + 51979 + 86193 69 | =642760 70 | --------------------------------------- 71 | 45032 + 54915 + 45158 + 55328 + 44954 + 54944 + 43798 + 45245 + 54905 + 43840 72 | =488119 73 | --------------------------------------- 74 | 76742 + 37695 + 76878 + 76867 + 37661 + 37645 + 37841 + 37655 + 76491 + 37624 75 | =533099 76 | --------------------------------------- 77 | 78 | 554659 79 | 80 | =======================================4 81 | 26919 + 26048 + 26039 + 231000 + 26246 + 26010 + 26967 + 26302 + 26962 + 198825 82 | =641318 83 | --------------------------------------- 84 | 226523 + 247425 + 27794 + 27821 + 27735 + 27785 + 27717 + 27729 + 27769 + 27850 85 | =696148 86 | --------------------------------------- 87 | 557537 + 25341 + 25492 + 25302 + 25491 + 25495 + 241950 + 25300 + 25452 + 25311 88 | =1002671 89 | --------------------------------------- 90 | 780045 91 | 92 | =======================================5 93 | 24107 + 24982 + 24960 + 24999 + 24093 + 24980 + 24057 + 24112 + 25042 + 24983 94 | =246315 95 | --------------------------------------- 96 | 16625 + 17119 + 16602 + 17001 + 17268 + 17010 + 17293 + 16627 + 17008 + 17120 97 | =169673 98 | --------------------------------------- 99 | 22322 + 21539 + 22637 + 22323 + 22336 + 22317 + 22246 + 21480 + 22336 + 21514 100 | =221050 101 | --------------------------------------- 102 | 212346 103 | ======================================= 104 | ======================================= 105 | ======================================= 106 | ======================================= 107 | 108 | 109 | import matplotlib.pyplot as plt 110 | from matplotlib.backends.backend_pdf import PdfPages 111 | 112 | base = [2480549, 1191693, 554659, 780045, 212346] 113 | 114 | x_tics = [1, 2, 3, 4, 5] 115 | 116 | plt.figure(num=None, figsize=(6, 3), dpi=80, facecolor='w', edgecolor='k') 117 | plt.plot(base, marker="o", linestyle="-", color='darkblue') 118 | plt.yscale('log') 119 | plt.xticks([0, 1, 2, 3, 4], x_tics) 120 | plt.ylabel("Appends/s") 121 | plt.xlabel("Colors per append") 122 | pp = PdfPages('tmp.pdf') 123 | pp.savefig(bbox_inches='tight') 124 | pp.close() 125 | plt.show() 126 | -------------------------------------------------------------------------------- /benchers/fuzzy_log_throughput/dataset1: -------------------------------------------------------------------------------- 1 | 2 | split with all clients going to all partitions 3 | 4 | =======================================1 5 | 409321+307453+389848+317346+256859+324368+272888+413639+255860+306854=3254436 6 | 7 | --------------------------------------- 8 | 428984+424402+350628+332480+452299+420974+422920+462395+542816+308702=4146600 9 | 10 | --------------------------------------- 11 | 478213+342967+399136+568209+332968+326061+467390+465743+423076+474543=4278306 12 | 13 | --------------------------------------- 14 | 15 | 3893114 16 | 17 | =======================================2 18 | 55485+56531+56627+55126+57023+55489+57623+55400+56826+57478=563608 19 | 20 | --------------------------------------- 21 | 57888+58741+57873+58987+60580+58335+58374+58945+59391+59171=588285 22 | 23 | --------------------------------------- 24 | 40993+42163+41413+41564+41113+41850+42252+41899+40983+42664=416894 25 | 26 | --------------------------------------- 27 | 28 | 522929 29 | 30 | =======================================3 31 | 44230+43942+43864+44487+43365+44609+42805+43526+43679+44461=438968 32 | 33 | --------------------------------------- 34 | 40289+40838+39921+40251+39232+39311+40323+40021+40766+40154=401106 35 | 36 | --------------------------------------- 37 | 29890+28998+29177+29913+29279+30208+29811+29828+30322+29736=297162 38 | 39 | --------------------------------------- 40 | 41 | 379078 42 | 43 | =======================================4 44 | 34004+34111+32004+33906+31945+34049+33831+34330+33897+32221=334298 45 | 46 | --------------------------------------- 47 | 26884+27145+26965+26954+27106+26848+27086+27131+26879+26956=269954 48 | 49 | --------------------------------------- 50 | 20170+20067+20172+20026+20043+20242+20162+20068+20296+20181=201427 51 | 52 | --------------------------------------- 53 | 54 | 268559 55 | 56 | =======================================5 57 | 27233+26472+27281+25790+27380+26461+27285+27228+25772+27273=268175 58 | 59 | --------------------------------------- 60 | 13663+13390+13856+13785+13849+13878+13790+13671+13891+13390=137163 61 | 62 | --------------------------------------- 63 | 17360+17379+16972+16986+17172+17282+17354+17138+17286+17133=172062 64 | 65 | --------------------------------------- 66 | 67 | 192466 68 | 69 | ======================================= 70 | ======================================= 71 | ======================================= 72 | ======================================= 73 | 380024+426722+480855+509553+412781+406897+538487+364468+623236+393164 74 | 4536187 75 | --------------------------------------- 76 | 450643+298944+624234+487451+311350+309729+454293+461047+560235+304411 77 | 4262337 78 | --------------------------------------- 79 | 769348+333854+347740+330828+329444+339161+776826+321431+346731+364038 80 | 4259401 81 | =======================================2 82 | 75468+74527+75694+77424+77136+75438+77166+77170+75178+77032 83 | 762233 84 | --------------------------------------- 85 | 79591+84088+84505+84907+79756+82153+83053+79937+85154+83665 86 | 826809 87 | --------------------------------------- 88 | 76493+76845+77187+80689+77275+79954+78513+80341+75170+77130 89 | 779597 90 | 91 | ======================================= 92 | ======================================= 93 | ======================================= 94 | ======================================= 95 | 96 | --------------------------------------- 97 | --------------------------------------- 98 | 99 | ======================================= 100 | 101 | ======================================= 102 | ======================================= 103 | ======================================= 104 | ======================================= 105 | 106 | 107 | import matplotlib.pyplot as plt 108 | from matplotlib.backends.backend_pdf import PdfPages 109 | 110 | base = [3893114, 522929, 379078, 268559, 192466] 111 | 112 | x_tics = [1, 2, 3, 4, 5] 113 | 114 | plt.figure(num=None, figsize=(6, 3), dpi=80, facecolor='w', edgecolor='k') 115 | plt.plot(base, marker="o", linestyle="-", color='darkblue') 116 | plt.yscale('log') 117 | plt.xticks([0, 1, 2, 3, 4], x_tics) 118 | plt.ylabel("Appends/s") 119 | plt.xlabel("Colors per append") 120 | pp = PdfPages('tmp.pdf') 121 | pp.savefig(bbox_inches='tight') 122 | pp.close() 123 | plt.show() 124 | -------------------------------------------------------------------------------- /benchers/fuzzy_log_throughput/dataset2: -------------------------------------------------------------------------------- 1 | 2 | split with extra chains 3 | 4 | =======================================1 5 | 227506+233925+240672+236625+213075+246274+229125+245286+218001+226965 6 | 2317454 7 | --------------------------------------- 8 | 248109+204318+242721+246600+202725+238050+251775+215325+191263+221175 9 | 2262061 10 | --------------------------------------- 11 | 223575+242175+197475+241125+246750+234932+218648+233175+215025+242903 12 | 2295783 13 | --------------------------------------- 14 | 2291766 15 | =======================================2 16 | 44571+46612+44542+77873+77851+44850+86832+86891+45184+45273 17 | 600479 18 | --------------------------------------- 19 | 56153+57586+79510+79724+56264+56177+77203+58617+57131+76648 20 | 655013 21 | --------------------------------------- 22 | 63295+75570+78583+65388+77953+75181+63285+64561+65281+63719 23 | 692816 24 | --------------------------------------- 25 | 649436 26 | =======================================3 27 | 32567+31715+29365+29514+31687+32326+31661+31612+29320+29600 28 | 309367 29 | --------------------------------------- 30 | 34513+34324+33707+33714+34065+34302+33722+34218+33698+34453 31 | 340716 32 | --------------------------------------- 33 | 45622+45411+43898+48846+43129+43515+48360+48861+48457+43206 34 | 459305 35 | --------------------------------------- 36 | 369796 37 | =======================================4 38 | 34685+33208+31841+33195+33196+33755+33700+31854+31816+32607 39 | 329857 40 | --------------------------------------- 41 | 32746+35291+32847+33598+33030+33418+33129+34352+32753+33370 42 | 334534 43 | --------------------------------------- 44 | 32003+31968+32367+33429+32087+32353+32113+31957+32883+32217 45 | 323377 46 | --------------------------------------- 47 | 329256 48 | =======================================5 49 | 26620+26639+26720+26708+26653+26577+26718+26684+26630+26603 50 | 266552 51 | --------------------------------------- 52 | 26958+27028+27083+26971+26979+26904+26990+27008+27101+27023 53 | 270045 54 | --------------------------------------- 55 | 24716+24853+24695+24783+24742+24784+24723+24867+24842+24710 56 | 247715 57 | --------------------------------------- 58 | 261437 59 | ======================================= 60 | ======================================= 61 | ======================================= 62 | ======================================= 63 | 64 | note: single appends need half the window of multis since they have half the latency 65 | 66 | 111111111111111111111111111111111111111 67 | 244741+243733+533620+594497+245502+506433+587084+542256+517229+241184 68 | 4256279 69 | --------------------------------------- 70 | 572728+536161+608151+597922+497950+484386+425004+516250+622789+602644 71 | 5463985 72 | --------------------------------------- 73 | 450477+582091+203771+517051+409426+256840+259454+205133+532754+590047 74 | 4007044 75 | --------------------------------------- 76 | 4575769 77 | 78 | 222222222222222222222222222222222222222 79 | 72808+108043+56453+56384+72479+73032+105438+56417+57483+72612 80 | 731149 81 | --------------------------------------- 82 | 81765+48508+47983+47956+81575+81296+48465+81255+48631+47884 83 | 615318 84 | --------------------------------------- 85 | 91922+75877+74994+92429+91860+75552+117621+72921+89414+117006 86 | 899596 87 | --------------------------------------- 88 | 748687 89 | 90 | 333333333333333333333333333333333333333 91 | 36804+34710+36364+37394+36913+36966+36872+35581+39081+37465 92 | 368150 93 | --------------------------------------- 94 | 41579+35274+41767+37092+36756+37476+41817+36025+35613+37407 95 | 380806 96 | --------------------------------------- 97 | 36413+36397+35754+36987+36475+37105+36499+35948+37550+36205 98 | 365333 99 | --------------------------------------- 100 | 371429 101 | 102 | 444444444444444444444444444444444444444 103 | 104 | 20615+20656+20596+20623+21295+21364+20621+21270+21273+21234 105 | 209547 106 | --------------------------------------- 107 | 23464+23397+29861+23397+23403+22674+28994+23389+23091+23079 108 | 244749 109 | --------------------------------------- 110 | 29460+29175+29626+53814+29122+29630+29755+29445+29171+57804 111 | 347002 112 | --------------------------------------- 113 | 22717+36676+36717+22688+22719+22349+22793+22917+22339+22334 114 | 254249 115 | --------------------------------------- 116 | 263886 117 | 118 | 555555555555555555555555555555555555555 119 | 23744+23685+23663+23888+23783+23732+23652+23796+23618+23756 120 | 237317 121 | --------------------------------------- 122 | 21497+21829+21603+21489+21578+21858+21885+21898+21475+21608 123 | 216720 124 | --------------------------------------- 125 | 20371+20314+19910+20034+19284+20392+20042+19274+19891 126 | 179512 127 | --------------------------------------- 128 | 25605+26099+25682+26784+26111+26863+26790+25686+26826+26104 129 | 262550 130 | --------------------------------------- 131 | 224024 132 | 133 | ======================================= 134 | ======================================= 135 | ======================================= 136 | ======================================= 137 | 138 | 139 | import matplotlib.pyplot as plt 140 | from matplotlib.backends.backend_pdf import PdfPages 141 | 142 | base = [4575769, 748687, 371429, 263886, 224024] 143 | 144 | x_tics = [1, 2, 3, 4, 5] 145 | 146 | plt.figure(num=None, figsize=(6, 3), dpi=80, facecolor='w', edgecolor='k') 147 | plt.plot(base, marker="o", linestyle="-", color='darkblue') 148 | plt.yscale('log') 149 | plt.xticks([0, 1, 2, 3, 4], x_tics) 150 | plt.ylabel("Appends/s") 151 | plt.xlabel("Colors per append") 152 | pp = PdfPages('tmp.pdf') 153 | pp.savefig(bbox_inches='tight') 154 | pp.close() 155 | plt.show() 156 | -------------------------------------------------------------------------------- /benchers/isolation/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "isol" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | crossbeam = "0.2.10" 8 | env_logger = "0.3" 9 | fuzzy_log_client = {path = "../../fuzzy_log_client"} 10 | log = "0.3" 11 | rand = "0.3" 12 | structopt = "0.0.5" 13 | structopt-derive = "0.0.5" 14 | 15 | [profile.release] 16 | opt-level = 3 17 | #debug = true 18 | debug = false 19 | rpath = false 20 | lto = false 21 | debug-assertions = false 22 | codegen-units = 1 23 | panic = 'abort' 24 | -------------------------------------------------------------------------------- /benchers/isolation/dataset0: -------------------------------------------------------------------------------- 1 | #Args { servers: ServerAddrs([(V4(172.31.15.138:13289), V4(172.31.2.64:13289)), (V4(172.31.6.234:13289), V4(172.31.4.131:13289))]), handles: 2, num_rounds: 5, ms_per_round: 2000, write_window: 1000, percent_multiappends: 1 } 2 | #2 servers 3 | #client 0 single 4 | #client 1 multi 5 | #throughput [[1099579, 1153664, 1147453, 1128815, 1139042], [618777, 591838, 593777, 602661, 599210]] 6 | #writes [AtomicUsize(1138347), AtomicUsize(580643)] 7 | #total_writes = [6807400, 3587417] 8 | #elapsed Duration { secs: 14, nanos: 6031206 } 9 | appends/s @ 1% = [566855, 300626] 10 | 11 | --------------------------------------- 12 | single, multi 13 | appends/s @ 1% = [566855, 300626] 14 | appends/s @ 5% = [558325, 276568] 15 | appends/s @ 10% = [444179, 258893] 16 | appends/s @ 20% = [467545, 241557] 17 | appends/s @ 30% = [504574, 249388] 18 | appends/s @ 40% = [525912, 213872] 19 | appends/s @ 50% = [560073, 194425] 20 | appends/s @ 100% = [549803, 177344] 21 | 22 | ======================================= 23 | ======================================= 24 | ======================================= 25 | ======================================= 26 | 27 | 28 | import matplotlib.pyplot as plt 29 | from matplotlib.backends.backend_pdf import PdfPages 30 | 31 | only_singles = [566855, 558325, 444179, 467545, 504574, 525912, 560073, 549803] 32 | also_multies = [300626 ,276568 ,258893 ,241557 ,249388 ,213872 ,194425 ,177344] 33 | 34 | x_tics = ["1%", "5%", "10%", "20%", "30%", "40%", "50%", "100%"] 35 | #x_tics = [1, 5, 10, 20, "30%", "40%", "50%", "100%"] 36 | 37 | plt.figure(num=None, figsize=(6, 3), dpi=80, facecolor='w', edgecolor='k') 38 | plt.plot(only_singles, marker="o", linestyle="-", color='darkblue') 39 | plt.plot(also_multies, marker="x", linestyle="--", color='darkred') 40 | plt.xticks([0, 1, 2, 3, 4, 5, 6, 7], x_tics) 41 | plt.ylabel("Appends/s") 42 | plt.xlabel("Percent multiappends") 43 | plt.legend(["only single", "also multi"], loc=5) 44 | pp = PdfPages('a.pdf') 45 | pp.savefig(bbox_inches='tight') 46 | pp.close() 47 | plt.show() 48 | -------------------------------------------------------------------------------- /benchers/isolation/get_ips.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | import boto3 3 | 4 | ec2client = boto3.client('ec2') 5 | response = ec2client.describe_instances() 6 | public_dns = [] 7 | private_ip = [] 8 | clients = [] 9 | servers = [] 10 | for reservation in response["Reservations"]: 11 | for instance in reservation["Instances"]: 12 | if instance[u'PublicDnsName'] != "": 13 | public_dns.append(instance[u'PublicDnsName']) 14 | private_ip.append(instance[u'PrivateIpAddress']) 15 | 16 | num_instances = len(private_ip) 17 | print(num_instances) 18 | num_clients = 1 19 | 20 | print(public_dns) 21 | print(len(public_dns)) 22 | print("") 23 | print("") 24 | print("Clients") 25 | print(public_dns[0:num_clients]) 26 | print("") 27 | print("Servers") 28 | print(public_dns[num_clients:]) 29 | print(private_ip[num_clients:]) 30 | print("") 31 | print("") 32 | print("Client Hosts") 33 | server_ips = "" 34 | for i in range(0, len(private_ip[num_clients:]), 2): 35 | server_ips = server_ips + private_ip[num_clients + i] + ":13289#" + private_ip[num_clients + i + 1] + ":13289^" 36 | print(server_ips) 37 | client_hosts = "" 38 | for client in public_dns[0:num_clients]: 39 | client_hosts = client_hosts + client + "," 40 | print(client_hosts) 41 | 42 | -------------------------------------------------------------------------------- /benchers/isolation/start_clients.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | 3 | import subprocess 4 | import sys 5 | 6 | server_ips = '172.31.15.138:13289#172.31.2.64:13289^172.31.6.234:13289#172.31.4.131:13289' 7 | hostnames = 'ec2-34-229-147-107.compute-1.amazonaws.com' 8 | 9 | command = 'mirror:cd ./benchers/isolation/ && cargo run --release -- -p 100 ' + server_ips 10 | 11 | p1 = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", hostnames, "mirror:rustup install 1.19.0 && rustup override set 1.19.0", command]) 12 | 13 | p1.wait() 14 | -------------------------------------------------------------------------------- /benchers/isolation/start_servers.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | 3 | import subprocess 4 | import sys 5 | 6 | server_dns = ['ec2-54-144-204-176.compute-1.amazonaws.com', 'ec2-34-228-144-254.compute-1.amazonaws.com', 'ec2-107-21-20-209.compute-1.amazonaws.com', 'ec2-54-208-77-113.compute-1.amazonaws.com'] 7 | server_ips = ['172.31.15.138', '172.31.2.64', '172.31.6.234', '172.31.4.131'] 8 | procs = [] 9 | 10 | # server_dns = ['ec2-52-72-66-109.compute-1.amazonaws.com', 'ec2-34-227-206-53.compute-1.amazonaws.com', 'ec2-34-229-205-4.compute-1.amazonaws.com', 'ec2-54-208-101-237.compute-1.amazonaws.com'] 11 | # server_ips = ['172.31.5.104', '172.31.14.200', '172.31.6.234', '172.31.3.204'] 12 | 13 | hostnames = "" 14 | ips = "" 15 | for i in range(0, len(server_dns)-2, 2): 16 | hostnames += server_dns[i] + "," + server_dns[i+1] + "," 17 | ips += server_ips[i] + "#" + server_ips[i+1] + "^" 18 | 19 | hostnames += server_dns[len(server_dns)-2] + "," + server_dns[len(server_dns)-1] 20 | ips += server_ips[len(server_dns)-2] + "#" + server_ips[len(server_dns)-1] 21 | 22 | command = "run_chain:chain_hosts=" + ips + ",nt=t" 23 | print(command) 24 | p = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", hostnames, "mirror:rustup install 1.19.0 && rustup override set 1.19.0", command]) 25 | p.wait() 26 | -------------------------------------------------------------------------------- /benchers/larger_ev/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "larger_ev" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | crossbeam = "0.2.10" 8 | env_logger = "0.3" 9 | fuzzy_log_client = {path = "../../fuzzy_log_client"} 10 | fuzzy_log_server = {path = "../../fuzzy_log_server"} 11 | log = "0.3" 12 | mio = "0.6.6" 13 | structopt = "0.0.5" 14 | structopt-derive = "0.0.5" 15 | -------------------------------------------------------------------------------- /benchers/larger_ev/src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate crossbeam; 2 | extern crate env_logger; 3 | extern crate fuzzy_log_client; 4 | extern crate fuzzy_log_server; 5 | 6 | extern crate structopt; 7 | #[macro_use] 8 | extern crate structopt_derive; 9 | 10 | use std::net::SocketAddr; 11 | use std::str::FromStr; 12 | use std::time::{Duration, Instant}; 13 | 14 | use fuzzy_log_client::fuzzy_log::log_handle::{LogHandle, GetRes}; 15 | use fuzzy_log_client::packets::{entry, order, OrderIndex}; 16 | 17 | use fuzzy_log_server::tcp::run_server; 18 | 19 | use structopt::StructOpt; 20 | 21 | #[derive(StructOpt, Debug)] 22 | #[structopt(name = "backpointer", about = "backpointer vs forward benchmark.")] 23 | struct Args { 24 | #[structopt(help = "FuzzyLog servers to run against.")] 25 | servers: SocketAddr, 26 | 27 | #[structopt(short="r", long="rounds", help = "number of rounds.", default_value = "10000")] 28 | num_rounds: usize, 29 | } 30 | 31 | fn main() { 32 | const NUM_EVENTS: usize = 100_000; 33 | // const NUM_EVENTS: usize = 10; 34 | let start_time = Instant::now(); 35 | let _ = env_logger::init(); 36 | let args @ Args{..} = StructOpt::from_args(); 37 | 38 | let addr = args.servers; 39 | ::std::thread::spawn(move || { 40 | let s = ::std::sync::atomic::AtomicUsize::new(0); 41 | run_server(addr, 0, 1, None, None, 1, &s) 42 | }); 43 | 44 | ::std::thread::yield_now(); 45 | 46 | let handle = LogHandle::unreplicated_with_servers(&[args.servers]) 47 | .chains(&[order::from(1), order::from(2)]) 48 | .reads_my_writes() 49 | .build(); 50 | 51 | let (mut reader, mut writer) = handle.split(); 52 | let test_start = Instant::now(); 53 | crossbeam::scope(|scope| { 54 | let sender = scope.spawn(|| { 55 | let data: Vec = (0..461u32).map(|i| i as u8).collect(); 56 | for _ in 0..NUM_EVENTS { 57 | writer.async_append(order::from(1), &data[..], &[]); 58 | let _ = writer.flush_completed_appends(); 59 | } 60 | let _ = writer.wait_for_all_appends(); 61 | }); 62 | 63 | 64 | let mut gotten = 0; 65 | while gotten < NUM_EVENTS { 66 | // reader.snapshot(order::from(1)); 67 | reader.take_snapshot(); 68 | while let Ok(..) = reader.get_next() { 69 | gotten += 1; 70 | } 71 | } 72 | sender.join(); 73 | 74 | }); 75 | let elapsed = test_start.elapsed(); 76 | println!("got {} events in {:?}, {}Hz", 77 | NUM_EVENTS, 78 | elapsed, 79 | 1_000_000_000.0 * NUM_EVENTS as f64 / elapsed.subsec_nanos() as f64 80 | ); 81 | println!("TEST Time {:?}", start_time.elapsed()); 82 | ::std::thread::yield_now(); 83 | } 84 | -------------------------------------------------------------------------------- /benchers/queue_bench/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "queue_bench" 3 | version = "0.1.0" 4 | authors = ["J "] 5 | 6 | [dependencies] 7 | mio = "0.6" 8 | nix = "*" 9 | env_logger = "0.3" 10 | libc = "0.2" 11 | fuzzy_log = {path = "../.."} 12 | 13 | [profile.release] 14 | opt-level = 3 15 | debug = true 16 | rpath = false 17 | lto = true 18 | debug-assertions = false 19 | codegen-units = 1 20 | panic = 'unwind' 21 | 22 | [features] 23 | default = ["fuzzy_log/no_trace"] 24 | -------------------------------------------------------------------------------- /benchers/queue_bench/src/main.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate fuzzy_log; 4 | extern crate mio; 5 | extern crate nix; 6 | extern crate env_logger; 7 | extern crate test; 8 | extern crate libc; 9 | 10 | use std::mem; 11 | use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering, AtomicPtr}; 12 | use std::sync::{mpsc, Arc}; 13 | use std::thread; 14 | 15 | use test::{Bencher, black_box}; 16 | 17 | use fuzzy_log::servers2::spmc; 18 | 19 | //based on http://www.1024cores.net/home/lock-free-algorithms/queues/non-intrusive-mpsc-node-based-queue 20 | 21 | struct Node { 22 | next: AtomicPtr, 23 | data: u64, 24 | } 25 | 26 | struct Receiver { 27 | tail: AtomicPtr, 28 | } 29 | 30 | #[derive(Clone)] 31 | struct Sender { 32 | head: Arc>, 33 | } 34 | 35 | 36 | fn channel() -> (Sender, Receiver) { 37 | let stub = Box::new(Node{ next: AtomicPtr::default(), data: 0 }); 38 | let stub = Box::into_raw(stub); 39 | let head = AtomicPtr::new(stub); 40 | let tail = AtomicPtr::new(stub); 41 | (Sender { head: Arc::new(head), }, Receiver { tail: tail, }) 42 | } 43 | 44 | impl Sender { 45 | fn send(&self, data: u64) { 46 | let node = Box::new(Node { next: AtomicPtr::default(), data: data }); 47 | let n = Box::into_raw(node); 48 | let prev = self.head.swap(n, Ordering::AcqRel); 49 | unsafe { 50 | (&*prev).next.store(n, Ordering::Release) 51 | } 52 | } 53 | } 54 | 55 | impl Receiver { 56 | fn try_recv(&mut self) -> Option { 57 | unsafe { 58 | let tail = *self.tail.get_mut(); 59 | let next = (&*tail).next.load(Ordering::Acquire); 60 | next.as_mut().map(|next| { 61 | *self.tail.get_mut() = next; 62 | next.data 63 | }) 64 | } 65 | } 66 | } 67 | 68 | macro_rules! bench_queue { 69 | ($bench_name:ident, $channel_creator:path) => ( 70 | #[bench] 71 | fn $bench_name(b: &mut Bencher) { 72 | static SERVER_READY: AtomicUsize = ATOMIC_USIZE_INIT; 73 | set_priority(); 74 | set_cpu(0); 75 | let (send1, mut recv1) = $channel_creator(); 76 | let (send2, mut recv2) = $channel_creator(); 77 | let (send11, send21) = (send1.clone(), send2.clone()); 78 | send1.send(1); 79 | send2.send(1); 80 | recv1.try_recv(); 81 | recv2.try_recv(); 82 | 83 | thread::spawn(move || { 84 | set_cpu(1); 85 | SERVER_READY.fetch_add(1, Ordering::SeqCst); 86 | loop { 87 | let mut msg; 88 | 'recv: loop { 89 | msg = recv1.try_recv().unwrap_or(0); 90 | if msg != 0 { break 'recv } 91 | } 92 | let _ = send2.send(black_box(msg)); 93 | } 94 | }); 95 | 96 | while SERVER_READY.load(Ordering::Acquire) < 1 {} 97 | 98 | b.iter(move || { 99 | let sum = 0u64; 100 | for _ in 0..100 { 101 | let _ = black_box(send1.send(0xff10bc1u64)); 102 | } 103 | for _ in 0..100 { 104 | let mut msg; 105 | 'recv: loop { 106 | msg = recv2.try_recv().unwrap_or(0); 107 | if msg != 0 { break 'recv } 108 | } 109 | sum.wrapping_add(black_box(msg)); 110 | } 111 | black_box(sum) 112 | }); 113 | drop((send11, send21)); 114 | } 115 | ); 116 | } 117 | 118 | bench_queue!(bench_mio, mio::channel::channel); 119 | bench_queue!(a_bench_mio_sync, mio_sync_channel); 120 | bench_queue!(a_bench_sync, sync_channel); 121 | bench_queue!(bench_mpsc, mpsc::channel); 122 | //bench_queue!(bench_spmc, spmc::channel); 123 | bench_queue!(new, channel); 124 | 125 | fn sync_channel() -> (mpsc::SyncSender, mpsc::Receiver) { 126 | mpsc::sync_channel(1024) 127 | } 128 | 129 | fn mio_sync_channel() -> (mio::channel::SyncSender, mio::channel::Receiver) { 130 | mio::channel::sync_channel(1024) 131 | } 132 | 133 | fn set_cpu(cpu_num: usize) { 134 | #[cfg(linux)] 135 | unsafe { 136 | let mut cpu_set = mem::zeroed(); 137 | libc::CPU_ZERO(&mut cpu_set); 138 | libc::CPU_SET(cpu_num, &mut cpu_set); 139 | let thread_id = libc::pthread_self(); 140 | let cpu_set_size = mem::size_of::(); 141 | let err = libc::pthread_setaffinity_np(thread_id, cpu_set_size, &cpu_set); 142 | if err != 0 { 143 | panic!("cpu set failed for cpu {}, thread_id {}", cpu_num, thread_id) 144 | } 145 | } 146 | } 147 | 148 | fn set_priority() { 149 | #[cfg(linux)] 150 | unsafe { 151 | let err = libc::setpriority(libc::PRIO_PROCESS as u32, 0, -20); 152 | if err != 0 { 153 | panic!("set priority failed") 154 | } 155 | } 156 | } 157 | 158 | fn main() { 159 | println!("Only use with bench"); 160 | } 161 | -------------------------------------------------------------------------------- /benchers/read_latency/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "latben" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | crossbeam = "0.2.10" 8 | env_logger = "0.3" 9 | fuzzy_log_client = {path = "../../fuzzy_log_client"} 10 | log = "0.3" 11 | mio = "0.6.6" 12 | structopt = "0.2" 13 | structopt-derive = "0.2" 14 | -------------------------------------------------------------------------------- /benchers/read_latency/get_ips.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | import boto3 3 | 4 | ec2client = boto3.client('ec2') 5 | response = ec2client.describe_instances() 6 | public_dns = [] 7 | private_ip = [] 8 | clients = [] 9 | servers = [] 10 | for reservation in response["Reservations"]: 11 | for instance in reservation["Instances"]: 12 | if instance[u'PublicDnsName'] != "": 13 | public_dns.append(instance[u'PublicDnsName']) 14 | private_ip.append(instance[u'PrivateIpAddress']) 15 | 16 | num_instances = len(private_ip) 17 | print(num_instances) 18 | num_clients = 1 19 | 20 | print(public_dns) 21 | print(len(public_dns)) 22 | print("") 23 | print("") 24 | print("Clients") 25 | print(public_dns[0:num_clients]) 26 | print("") 27 | print("Servers") 28 | print(public_dns[num_clients:]) 29 | print(private_ip[num_clients:]) 30 | print("") 31 | print("") 32 | print("Client Hosts") 33 | server_ips = "" 34 | for i in range(0, len(private_ip[num_clients:]), 2): 35 | server_ips = server_ips + private_ip[num_clients + i] + ":13289^" + private_ip[num_clients + i + 1] + ":13289" 36 | print(server_ips) 37 | client_hosts = "" 38 | for client in public_dns[0:num_clients]: 39 | client_hosts = client_hosts + client + "," 40 | print(client_hosts) 41 | 42 | -------------------------------------------------------------------------------- /benchers/read_latency/read_experiment.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | 3 | import os 4 | import subprocess 5 | import sys 6 | import time 7 | 8 | def run(experiment, num_chains, nodes_per_chain): 9 | 10 | server_ip = '172.31.5.245:13289' 11 | ips = '172.31.5.245' 12 | server_hostnames = 'ec2-54-235-33-196.compute-1.amazonaws.com' 13 | 14 | client_hostnames = ['ec2-54-87-195-25.compute-1.amazonaws.com'] 15 | 16 | clients = client_hostnames[0] 17 | 18 | command = "run_chain:chain_hosts=" + ips 19 | 20 | s = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", 21 | server_hostnames, command]) 22 | 23 | time.sleep(2) 24 | 25 | ######################################## 26 | 27 | command = 'mirror:pkill latben; cd benchers/read_latency/ &&' + \ 28 | ' cargo run --release --' + \ 29 | ' ' + str(server_ip) + \ 30 | ' ' + experiment + \ 31 | ' ' + str(num_chains) + \ 32 | ' ' + str(nodes_per_chain) 33 | 34 | v = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", clients, 35 | command]) 36 | 37 | v.wait() 38 | s.kill() 39 | 40 | print("") 41 | print("> ") 42 | print("========================================") 43 | print("> ----------------------------------------") 44 | print("========================================") 45 | print("> ") 46 | print("") 47 | sys.stdout.flush() 48 | 49 | subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", server_hostnames, "kill_server"]) 50 | # subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", clients, 'mirror:pkill latben']) 51 | 52 | 53 | os.chdir('../..') 54 | 55 | # run("no_link", 1, 1) 56 | # exit(0) 57 | 58 | for experiment in ["zigzag"]: #["no_link", "zigzag"]: 59 | # print("> " + experiment) 60 | 61 | 62 | for num_chains in [1, 2, 10, 100]: 63 | # print(str(num_chains) + " chains") 64 | 65 | for nodes_per_chain in [1, 10, 100, 1000]: 66 | sys.stdout.flush() 67 | run(experiment, num_chains, nodes_per_chain) 68 | -------------------------------------------------------------------------------- /benchers/read_latency/start_clients.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | 3 | import subprocess 4 | import sys 5 | 6 | server_ips = '172.31.15.138:13289^172.31.4.131:13289' 7 | hostname = 'ec2-54-86-154-231.compute-1.amazonaws.com' 8 | 9 | command = 'mirror:cd ./benchers/backpointer/ && cargo run --release -- ' + server_ips 10 | 11 | p1 = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", hostname, "mirror:pkill back; rustup install 1.19.0 && rustup override set 1.19.0", command]) 12 | 13 | p1.wait() 14 | -------------------------------------------------------------------------------- /benchers/read_latency/start_servers.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | 3 | import subprocess 4 | import sys 5 | 6 | server_dns = ['ec2-107-20-87-53.compute-1.amazonaws.com', 'ec2-54-162-154-10.compute-1.amazonaws.com'] 7 | server_ips = ['172.31.15.138', '172.31.4.131'] 8 | procs = [] 9 | 10 | hostnames = "" 11 | ips = "" 12 | 13 | hostnames += server_dns[0] + "," + server_dns[1] 14 | ips += server_ips[0] + "^" + server_ips[1] 15 | 16 | command = "run_chain:chain_hosts=" + ips + ",nt=t" 17 | print(command) 18 | p0 = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", hostnames, "mirror:rustup install 1.19.0 && rustup override set 1.19.0", command]) 19 | 20 | p0.wait() 21 | -------------------------------------------------------------------------------- /benchers/replicated_failure/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "failure" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | env_logger = "0.3" 8 | fuzzy_log = {path = "../.."} 9 | mio = "0.6.6" 10 | -------------------------------------------------------------------------------- /benchers/scaling/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "scalben" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | crossbeam = "0.2.10" 8 | env_logger = "0.3" 9 | fuzzy_log_client = {path = "../../fuzzy_log_client"} 10 | fuzzy_log_util = {path = "../../fuzzy_log_util"} 11 | log = "0.3" 12 | rand = "0.3" 13 | structopt = "0.0.5" 14 | structopt-derive = "0.0.5" 15 | 16 | [profile.release] 17 | opt-level = 3 18 | #debug = true 19 | debug = false 20 | rpath = false 21 | lto = false 22 | debug-assertions = false 23 | codegen-units = 1 24 | panic = 'abort' 25 | -------------------------------------------------------------------------------- /benchers/scaling/get_ips.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python 2 | import boto3 3 | 4 | ec2client = boto3.client('ec2') 5 | response = ec2client.describe_instances() 6 | public_dns = [] 7 | private_ip = [] 8 | clients = [] 9 | servers = [] 10 | for reservation in response["Reservations"]: 11 | for instance in reservation["Instances"]: 12 | if instance[u'PublicDnsName'] != "": 13 | public_dns.append(instance[u'PublicDnsName']) 14 | private_ip.append(instance[u'PrivateIpAddress']) 15 | 16 | num_instances = len(private_ip) 17 | print(num_instances) 18 | num_clients = len(public_dns) - 11 19 | 20 | all_hosts = "" 21 | for host in public_dns: 22 | all_hosts = all_hosts + host + "," 23 | 24 | print(all_hosts) 25 | 26 | print(public_dns) 27 | print(len(public_dns)) 28 | print("") 29 | print("") 30 | 31 | print("clients") 32 | print(public_dns[0:num_clients]) 33 | print("") 34 | client_names = public_dns[0] 35 | for name in public_dns[1:num_clients]: 36 | client_names += "," + name 37 | print("") 38 | 39 | print("Servers") 40 | print(public_dns[num_clients:]) 41 | print("") 42 | print(private_ip[num_clients:-1]) 43 | print("") 44 | server_names = public_dns[num_clients] 45 | for name in public_dns[num_clients+1:-1]: 46 | server_names += "," + name 47 | print(server_names) 48 | print("") 49 | print(public_dns[-1]) 50 | print(private_ip[-1]) 51 | print("") 52 | -------------------------------------------------------------------------------- /benchers/scaling/run_experiment.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python 2 | 3 | import os 4 | import subprocess 5 | import sys 6 | import time 7 | 8 | def run(corfu, num_clients, handles_per_client, tx_in, window=750): 9 | 10 | data_server_ips = '172.31.13.138:13289#172.31.3.204:13289^172.31.9.12:13289#172.31.14.212:13289^172.31.11.45:13289#172.31.5.245:13289^172.31.0.84:13289#172.31.3.165:13289^172.31.6.77:13289#172.31.4.131:13289' 11 | seq_ips = '172.31.9.164:13289' 12 | 13 | ds_ips = '172.31.13.138#172.31.3.204^172.31.9.12#172.31.14.212^172.31.11.45#172.31.5.245^172.31.0.84#172.31.3.165^172.31.6.77#172.31.4.131' 14 | s_ips = '172.31.9.164' 15 | 16 | data_hostnames = 'ec2-34-201-119-82.compute-1.amazonaws.com,ec2-18-232-139-180.compute-1.amazonaws.com,ec2-54-165-208-168.compute-1.amazonaws.com,ec2-18-205-20-202.compute-1.amazonaws.com,ec2-52-90-172-135.compute-1.amazonaws.com,ec2-34-229-75-136.compute-1.amazonaws.com,ec2-35-172-219-199.compute-1.amazonaws.com,ec2-54-198-108-43.compute-1.amazonaws.com,ec2-52-90-95-50.compute-1.amazonaws.com,ec2-54-166-120-151.compute-1.amazonaws.com' 17 | 18 | seq_hostnames = 'ec2-34-224-64-30.compute-1.amazonaws.com' 19 | 20 | client_hostnames = ['ec2-34-224-58-29.compute-1.amazonaws.com', 'ec2-54-91-138-174.compute-1.amazonaws.com', 'ec2-54-90-149-215.compute-1.amazonaws.com', 'ec2-18-232-182-253.compute-1.amazonaws.com', 'ec2-34-234-74-251.compute-1.amazonaws.com', 'ec2-54-164-53-1.compute-1.amazonaws.com', 'ec2-34-228-199-156.compute-1.amazonaws.com', 'ec2-54-146-157-61.compute-1.amazonaws.com', 'ec2-54-89-232-100.compute-1.amazonaws.com'] 21 | 22 | print(len(client_hostnames)) 23 | 24 | client_hostnames = client_hostnames[:num_clients] 25 | num_clients = len(client_hostnames) 26 | 27 | clients = client_hostnames[0] 28 | for name in client_hostnames[1:]: 29 | clients += ',' + name 30 | 31 | 32 | command = "run_chain:chain_hosts=" + ds_ips 33 | d = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", 34 | data_hostnames, command]) 35 | 36 | command = "run_chain:chain_hosts=" + s_ips 37 | s = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", 38 | seq_hostnames, command]) 39 | 40 | time.sleep(5) 41 | 42 | ######################################## 43 | 44 | command = 'mirror:pkill scalben; cd benchers/scaling/ &&' + \ 45 | ' cargo run --release --' + \ 46 | ' ' + str(data_server_ips) + \ 47 | ' ' + str(seq_ips) + \ 48 | ' #server_num' + \ 49 | ' -h ' + str(handles_per_client) +\ 50 | ' -w ' + str(window) 51 | 52 | if tx_in != 0: 53 | command += ' -t ' + str(tx_in) 54 | 55 | if corfu: 56 | command += ' -c' 57 | 58 | print(clients) 59 | print(command) 60 | 61 | v = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", clients, 62 | command]) 63 | 64 | v.wait() 65 | s.kill() 66 | d.kill() 67 | 68 | print("") 69 | print("> ") 70 | print("========================================") 71 | print("> ----------------------------------------") 72 | print("========================================") 73 | print("> ") 74 | print("") 75 | sys.stdout.flush() 76 | 77 | k0 = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", data_hostnames, "kill_server"]) 78 | k1 = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", seq_hostnames, "kill_server"]) 79 | k2 = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", data_hostnames, "try_ex:pkill scalben"]) 80 | k0.wait() 81 | k1.wait() 82 | k2.wait() 83 | 84 | 85 | os.chdir('../..') 86 | 87 | # run(False, 9, 2, 1) 88 | 89 | # run(False, 1, 2, 1) 90 | # exit(0) 91 | 92 | # for num_clients in range(1, 9): 93 | # sys.stdout.flush() 94 | # run(False, num_clients, 2, 1) 95 | 96 | # exit(0) 97 | 98 | for corfu in [False]: 99 | if corfu: 100 | print("> corfu") 101 | else: 102 | print("> fuzzy") 103 | 104 | for tx_in in [0, 1000, 100, 10, 1]: 105 | if tx_in == 0: 106 | print("> 0%") 107 | else: 108 | print("> " + str(100.0/tx_in) + "%") 109 | 110 | for num_clients in range(1, 9): 111 | sys.stdout.flush() 112 | run(corfu, num_clients, 2, tx_in) 113 | 114 | -------------------------------------------------------------------------------- /benchers/throughput/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fuzzy_log_throughput_bench" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman "] 5 | 6 | [dependencies] 7 | clap = "2.24" 8 | env_logger = "0.3" 9 | fuzzy_log = {path = "../.."} 10 | log = "0.3" 11 | mio = "0.6.6" 12 | num_cpus = "1" 13 | rand = "0.3" 14 | 15 | [profile.release] 16 | opt-level = 3 17 | debug = true 18 | rpath = false 19 | #lto = true 20 | lto = false 21 | debug-assertions = false 22 | #debug-assertions = true 23 | codegen-units = 1 24 | panic = 'abort' 25 | 26 | [features] 27 | default = ["fuzzy_log/no_trace", "log/max_level_info"] 28 | print_stats = ["fuzzy_log/print_stats"] 29 | -------------------------------------------------------------------------------- /benchers/throughput/src/servers.rs: -------------------------------------------------------------------------------- 1 | 2 | use std::net::{SocketAddr, IpAddr, Ipv4Addr}; 3 | use std::sync::atomic::AtomicUsize; 4 | 5 | use mio; 6 | 7 | use fuzzy_log::servers2; 8 | 9 | pub fn run( 10 | port: u16, 11 | workers: usize, 12 | upstream: Option, 13 | downstream: Option, 14 | group: Option<(u32, u32)>, 15 | ) -> ! { 16 | let a = AtomicUsize::new(0); 17 | let (server_num, group_size) = group.unwrap_or((0, 1)); 18 | let replicated = upstream.is_some() || downstream.is_some(); 19 | let ip_addr = IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)); 20 | let addr = SocketAddr::new(ip_addr, port); 21 | let acceptor = mio::tcp::TcpListener::bind(&addr); 22 | match acceptor { 23 | Ok(accept) => if replicated { 24 | servers2::tcp::run_with_replication(accept, server_num, group_size, 25 | upstream, downstream, workers, &a) 26 | } else { 27 | servers2::tcp::run(accept, server_num, group_size, workers, &a) 28 | }, 29 | Err(e) => panic!("Could not start server due to {}.", e), 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /benchers/trivial_server/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | *.rlib 4 | *.a 5 | *.o 6 | out 7 | -------------------------------------------------------------------------------- /benchers/trivial_server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "trivial_server" 3 | version = "0.1.0" 4 | authors = ["J "] 5 | 6 | [dependencies] 7 | mio = "0.6" 8 | nix = "*" 9 | env_logger = "0.3" 10 | fuzzy_log = {path = "../.."} 11 | 12 | [profile.release] 13 | opt-level = 3 14 | debug = true 15 | rpath = false 16 | lto = true 17 | debug-assertions = false 18 | #debug-assertions = true 19 | codegen-units = 1 20 | panic = 'unwind' 21 | 22 | [features] 23 | default = ["fuzzy_log/no_trace"] 24 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | extern crate cbindgen; 2 | 3 | 4 | use std::{ 5 | env, 6 | path::Path, 7 | }; 8 | 9 | fn main() { 10 | let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); 11 | let crate_dir: &Path = crate_dir.as_ref(); 12 | 13 | match cbindgen::generate(crate_dir) { 14 | Ok(bindings) => { bindings.write_to_file("fuzzylog.h"); }, 15 | Err(e) => eprintln!("{}", e), 16 | } 17 | 18 | let ext_toml = "cbindgen_async_ext.toml"; 19 | let config = crate_dir.join(ext_toml); 20 | match config.exists() { 21 | true => { 22 | let mut config = cbindgen::Config::from_file(config.to_str().unwrap()).unwrap(); 23 | config.sys_includes.push("fuzzylog.h".to_owned()); 24 | match cbindgen::generate_with_config(crate_dir, config) { 25 | Ok(bindings) => { bindings.write_to_file("fuzzylog_async_ext.h"); }, 26 | Err(e) => eprintln!("{}", e), 27 | } 28 | }, 29 | false => panic!("{:?} does not exist", config), 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /cbindgen.toml: -------------------------------------------------------------------------------- 1 | 2 | include_guard = "FuzzyLog_C_bindings_h" 3 | autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */" 4 | include_version = true 5 | braces = "SameLine" 6 | line_length = 80 7 | tab_width = 4 8 | language = "C" 9 | style = "Type" 10 | documentation = true 11 | 12 | [parse] 13 | parse_deps = false 14 | 15 | [export] 16 | exclude = [ 17 | "WriteId", "WriteIdAndLocs", "Box_DAG", "HashMap_order__entry", "ReaderAndWriter", "Vals", 18 | "async_causal_append", "async_get_next2", "async_no_remote_append", 19 | "async_simple_causal_append", "do_append", "flush_completed_appends", 20 | "get_next", "get_next2", "new_dag_handle", "new_dag_handle_from_config", 21 | "new_dag_handle_with_replication", "new_dag_handle_with_skeens", 22 | "no_remote_append", "snapshot", "snapshot_colors", "split_dag_handle", 23 | "start_fuzzy_log_server_thread", "start_fuzzy_log_server_thread_from_group", 24 | "start_servers_from_config", "try_wait_for_any_append", 25 | "try_wait_for_any_append_and_location", "wait_for_a_specific_append", 26 | "wait_for_a_specific_append_and_locations", "wait_for_all_appends", 27 | "wait_for_any_append", "close_dag_handle", "ColorId", "colors", "fuzzylog_async_append", 28 | "fuzzylog_try_wait_for_any_append", "fuzzylog_wait_for_any_append", "fuzzylog_wait_for_all_appends", "fuzzylog_wait_for_a_specific_append", "fuzzylog_sync_events", "FuzzyLogEvent", "fuzzylog_sync_chain", 29 | "fuzzylog_event_inhabits_chain"] 30 | 31 | [fn] 32 | args = "Auto" 33 | -------------------------------------------------------------------------------- /cbindgen_async_ext.toml: -------------------------------------------------------------------------------- 1 | 2 | include_guard = "FuzzyLog_C_async_ext_h" 3 | autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */" 4 | include_version = true 5 | braces = "SameLine" 6 | line_length = 80 7 | tab_width = 4 8 | language = "C" 9 | style = "Type" 10 | documentation = true 11 | 12 | [parse] 13 | parse_deps = false 14 | 15 | [export] 16 | exclude = [ 17 | "WriteIdAndLocs", "Box_DAG", "HashMap_order__entry", "ReaderAndWriter", "Vals", 18 | "async_causal_append", "async_get_next2", "async_no_remote_append", 19 | "async_simple_causal_append", "do_append", "flush_completed_appends", 20 | "get_next", "get_next2", "new_dag_handle", "new_dag_handle_from_config", 21 | "new_dag_handle_with_replication", "new_dag_handle_with_skeens", 22 | "no_remote_append", "snapshot", "snapshot_colors", "split_dag_handle", 23 | "start_fuzzy_log_server_thread", "start_fuzzy_log_server_thread_from_group", 24 | "start_servers_from_config", "try_wait_for_any_append_and_location", 25 | "wait_for_a_specific_append_and_locations", "close_dag_handle", "ColorId", 26 | "colors", "ColorSpec", "ServerSpec", "FLPtr", "SnapId", "delete_snap_id", 27 | "fuzzylog_append", "fuzzylog_close", "fuzzylog_sync", "fuzzylog_trim", 28 | "new_fuzzylog_instance", "HashMap", "try_wait_for_any_append", "wait_for_a_specific_append", 29 | "wait_for_all_appends", "wait_for_any_append", "fuzzylog_sync_chain"] 30 | 31 | [fn] 32 | args = "Auto" 33 | -------------------------------------------------------------------------------- /cleaner.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This a simple bash script to run `cargo clean` recursively. 4 | # 5 | # Usage: `bash cargo-clean.sh target_dir` 6 | 7 | clean_recursive() { 8 | # First, check whether current directiry is the root of a cargo project. 9 | if [ -f "Cargo.toml" ]; then 10 | echo "Cleaning \"$(pwd)\"" 11 | cargo clean 12 | fi 13 | # Then, visit the sub directory. 14 | for path in `ls`; do 15 | if [ -d $path ]; then 16 | cd $path 17 | clean_recursive 18 | cd .. 19 | fi 20 | done 21 | } 22 | 23 | main() { 24 | if [ x$1 != x ]; then 25 | if [ -d $1 ]; then 26 | cd $1 27 | else 28 | echo "Error: $1 is not a directory, done." 29 | fi 30 | else 31 | cd . 32 | fi 33 | 34 | echo "Scanning \"$(pwd)\"" 35 | clean_recursive 36 | echo "Done." 37 | } 38 | 39 | main $* 40 | 41 | -------------------------------------------------------------------------------- /examples/c_linking/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | *.rlib 4 | *.a 5 | *.o 6 | out 7 | -------------------------------------------------------------------------------- /examples/c_linking/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "c_link" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman "] 5 | 6 | [dependencies] 7 | fuzzy_log = {path = "../.."} 8 | 9 | [lib] 10 | crate-type = ["staticlib", "dylib"] 11 | 12 | [profile.release] 13 | opt-level = 3 14 | debug = true 15 | rpath = false 16 | lto = false 17 | debug-assertions = false 18 | codegen-units = 1 19 | panic = 'unwind' 20 | -------------------------------------------------------------------------------- /examples/c_linking/Makefile: -------------------------------------------------------------------------------- 1 | #USAGE 2 | # 3 | # make [all] builds and links example, placing it in ./out/start 4 | # 5 | # make rust_code builds the delos-rust library in ./target/release/ 6 | # 7 | # make mostlyclean removes artifacts (object files and binaries) generated from C code 8 | # make rust_clean removes artifacts generated from rust code 9 | # make clean removes all generated artifacts 10 | # 11 | # make new_dir DIR_NAME= 12 | # Creates a new copy of this makefile and necessary code in directory 13 | # such that the above commands will work in said directory 14 | # this relies on the enviroment variable DELOS_RUST_LOC being set to the 15 | # location of a local copy of the delos-rust repository. 16 | 17 | C_SRC := start.c 18 | 19 | DELOS_RUST_LOC ?= ../.. 20 | 21 | LINK_FLAGS += -L$(DELOS_RUST_LOC)/examples/c_linking/target/release -lc_link -lm -ldl -lrt -pthread -Wl,--gc-sections 22 | MAC_LINK_FLAGS += -L$(DELOS_RUST_LOC)/examples/c_linking/target/release -lc_link -lsystem -lc -lm -pthread 23 | 24 | CFLAGS += -O2 -std=gnu11 25 | WFLAGS += -Wall -Wextra -Wpointer-arith -Wundef -Wformat=2 -Wnested-externs 26 | 27 | .PHONY: all rust_code clean mostlyclean rust_clean new_dir 28 | 29 | all: out/start 30 | 31 | out/start: $(DELOS_RUST_LOC)/examples/c_linking/target/release/libc_link.a $(C_SRC) 32 | @mkdir -p ./out 33 | $(CC) start.c -o ./out/start $(CFLAGS) $(WFLAGS) $(LINK_FLAGS) 34 | 35 | rust_code: $(DELOS_RUST_LOC)/examples/c_linking/target/release/libc_link.a 36 | 37 | 38 | $(DELOS_RUST_LOC)/examples/c_linking/target/release/libc_link.a: $(shell find $(DELOS_RUST_LOC)/src/ -type f) 39 | @echo "Building fuzzy log @ $(DELOS_RUST_LOC)/examples/c_linking/" 40 | @{ cd $(DELOS_RUST_LOC)/examples/c_linking/ && cargo build --release; } || \ 41 | { echo "\033[0;31mHave you set DELOS_RUST_LOC?\033[0m" && exit 1; } 42 | 43 | clean: rust_clean mostlyclean 44 | 45 | mostlyclean: 46 | rm -rf ./out 47 | 48 | rust_clean: 49 | @echo "Cleaning $(DELOS_RUST_LOC)/examples/c_linking/" 50 | @cd $(DELOS_RUST_LOC)/examples/c_linking/ && cargo clean 51 | 52 | DONT_COPY = target out Cargo.lock Cargo.toml src 53 | 54 | new_dir: 55 | ifeq ($(strip $(DIR_NAME)),) 56 | @echo "DIR_NAME must be non-empty" 57 | else 58 | @echo "Setting up in $(abspath $(DIR_NAME))" 59 | @mkdir -p $(abspath $(DIR_NAME)) 60 | @cp -R $(filter-out $(DONT_COPY), $(wildcard *)) $(abspath $(DIR_NAME)) 61 | @echo "\tfuzzylog @ $(abspath ../..)" 62 | ifeq ($(DELOS_RUST_LOC), ) 63 | @echo "run\n\texport DELOS_RUST_LOC=$(abspath ../..)\nto enable linking." 64 | endif 65 | ifeq ($(DELOS_RUST_LOC), ../..) 66 | @echo "run\n\t\033[0;37mexport DELOS_RUST_LOC=$(abspath ../..)\033[0m\nto enable linking." 67 | endif 68 | endif 69 | -------------------------------------------------------------------------------- /examples/c_linking/Readme.md: -------------------------------------------------------------------------------- 1 | # C Linking Example 2 | This directory contains a header file [`fuzzy_log.h`](fuzzy_log.h) 3 | which can be used to link C programs to the FuzzyLog client API, 4 | along with an example of such a program, and a Makefile which 5 | hopefully makes such linking simple. 6 | 7 | ## Building the Example 8 | 9 | Make sure you have `rust` intalled 10 | (run `curl https://sh.rustup.rs -sSf | sh` if not) 11 | and `make`. 12 | 13 | **MAC OS Note**: Due to differences in linking on MAC OS and linux 14 | the Makfile provides a seperate set of linker flags for MAC OS. 15 | If you wish to run this example on mac you must first replace 16 | `LINK_FLAGS` with `MAC_LINK_FLAGS` in the Makefile. 17 | 18 | Run `make` this will ouput the example binary in `./out/start`. 19 | This binary is standalone, it starts up its own instance of the 20 | FuzzyLog server at `127.0.0.1:13229` to run against, 21 | starts a client, performs some appends and reads them back. 22 | 23 | ## Starting you own project 24 | 25 | To create your own FuzzyLog project, use the command 26 | 27 | make new_dir DIR_NAME= 28 | 29 | which will copy the relevent files to . 30 | Then set the enviroment variable `DELOS_RUST_LOC` to the location 31 | of your local copy of the `delos-rust` repo. 32 | (In the examples folder a simple copy-paste will suffice). 33 | 34 | **MAC OS Note**: Due to differences in linking on MAC OS and linux 35 | the Makfile provides a seperate set of linker flags for MAC OS. 36 | If you wish to run your code on mac you must first replace 37 | `LINK_FLAGS` with `MAC_LINK_FLAGS` in the Makefile. 38 | 39 | An example of a project wich was created using this method can be 40 | found in [examples/c_multi_server](../c_multi_server). 41 | 42 | See [`fuzzy_log.h`](fuzzy_log.h) for the FuzzyLog functions currently available. 43 | -------------------------------------------------------------------------------- /examples/c_linking/src/lib.rs: -------------------------------------------------------------------------------- 1 | 2 | extern crate fuzzy_log; 3 | 4 | pub use fuzzy_log::c_binidings::*; 5 | 6 | -------------------------------------------------------------------------------- /examples/c_linking/start.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "fuzzy_log.h" 6 | 7 | static char *server_ip = "127.0.0.1:13229"; 8 | 9 | static char out[DELOS_MAX_DATA_SIZE]; 10 | 11 | int main() 12 | { 13 | start_fuzzy_log_server_thread("0.0.0.0:13229"); 14 | 15 | struct colors color = { .numcolors = 3, .mycolors = (ColorID[]){2, 3, 4}}; 16 | struct DAGHandle* dag = new_dag_handle_for_single_server(server_ip, &color); 17 | printf("fuzzy log client at %p.\n", dag); 18 | 19 | uint32_t data; 20 | { 21 | data = 401; 22 | color.mycolors = (ColorID[]){4}; 23 | color.numcolors = 1; 24 | printf("sending %d to %d.\n", data, color.mycolors[0]); 25 | append(dag, (char *)&data, sizeof(data), &color, NULL); 26 | } 27 | { 28 | data = 102; 29 | color.mycolors = (ColorID[]){2}; 30 | color.numcolors = 1; 31 | printf("sending %d to %d.\n", data, color.mycolors[0]); 32 | append(dag, (char *)&data, sizeof(data), &color, NULL); 33 | } 34 | { 35 | data = 733; 36 | color.mycolors = (ColorID[]){3};; 37 | color.numcolors = 1; 38 | printf("sending %d to %d.\n", data, color.mycolors[0]); 39 | append(dag, (char *)&data, sizeof(data), &color, NULL); 40 | } 41 | uint32_t end_key; 42 | { 43 | srand(time(NULL)); 44 | end_key = rand(); 45 | data = end_key; 46 | color.mycolors = (ColorID[]){2, 3, 4}; 47 | color.numcolors = 3; 48 | printf("sending %d to all.\n", data); 49 | append(dag, (char *)&data, sizeof(data), &color, NULL); 50 | } 51 | 52 | snapshot(dag); 53 | 54 | while (color.numcolors != 0) { 55 | size_t size = 0; 56 | get_next(dag, out, &size, &color); 57 | if (color.numcolors != 0) { 58 | printf("read %zu bytes = %d from", size, *(uint32_t *)out); 59 | for(size_t i = 0; i < color.numcolors; i++) { 60 | printf(" %d", color.mycolors[i]); 61 | } 62 | printf(".\n"); 63 | } 64 | else { 65 | printf("finished reading.\n"); 66 | } 67 | } 68 | 69 | close_dag_handle(dag); 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /examples/c_multi_server/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | *.rlib 4 | *.a 5 | *.o 6 | out 7 | -------------------------------------------------------------------------------- /examples/c_multi_server/Makefile: -------------------------------------------------------------------------------- 1 | #USAGE 2 | # 3 | # make [all] builds and links example, placing it in ./out/start 4 | # 5 | # make rust_code builds the delos-rust library in ./target/release/ 6 | # 7 | # make mostlyclean removes artifacts (object files and binaries) generated from C code 8 | # make rust_clean removes artifacts generated from rust code 9 | # make clean removes all generated artifacts 10 | # 11 | # make new_dir DIR_NAME= 12 | # Creates a new copy of this makefile and necessary code in directory 13 | # such that the above commands will work in said directory 14 | # this relies on the enviroment variable DELOS_RUST_LOC being set to the 15 | # location of a local copy of the delos-rust repository. 16 | 17 | C_SRC := start.c 18 | 19 | DELOS_RUST_LOC ?= ../.. 20 | 21 | LINK_FLAGS += -L$(DELOS_RUST_LOC)/examples/c_linking/target/release -lc_link -pthread 22 | MAC_LINK_FLAGS += -L$(DELOS_RUST_LOC)/examples/c_linking/target/release -lc_link -lsystem -lc -lm -pthread 23 | 24 | CFLAGS += -O2 -std=gnu11 25 | WFLAGS += -Wall -Wextra -Wpointer-arith -Wundef -Wformat=2 -Wnested-externs 26 | 27 | .PHONY: all rust_code clean mostlyclean rust_clean new_dir 28 | 29 | all: $(DELOS_RUST_LOC)/examples/c_linking/target/release/libc_link.a 30 | @mkdir -p ./out 31 | $(CC) start.c -o ./out/start $(CFLAGS) $(WFLAGS) $(LINK_FLAGS) 32 | 33 | rust_code: $(DELOS_RUST_LOC)/examples/c_linking/target/release/libc_link.a 34 | 35 | 36 | $(DELOS_RUST_LOC)/examples/c_linking/target/release/libc_link.a: $(shell find $(DELOS_RUST_LOC)/src/ -type f) 37 | @echo "Building fuzzy log @ $(DELOS_RUST_LOC)/examples/c_linking/" 38 | @{ cd $(DELOS_RUST_LOC)/examples/c_linking/ && cargo build --release; } || \ 39 | { echo "\033[0;31mHave you set DELOS_RUST_LOC?\033[0m" && exit 1; } 40 | 41 | clean: rust_clean mostlyclean 42 | 43 | mostlyclean: 44 | rm -rf ./out 45 | 46 | rust_clean: 47 | @echo "Cleaning $(DELOS_RUST_LOC)/examples/c_linking/" 48 | @cd $(DELOS_RUST_LOC)/examples/c_linking/ && cargo clean 49 | 50 | DONT_COPY = target out Cargo.lock Cargo.toml src 51 | 52 | new_dir: 53 | ifeq ($(strip $(DIR_NAME)),) 54 | @echo "DIR_NAME must be non-empty" 55 | else 56 | @echo "Setting up in $(abspath $(DIR_NAME))" 57 | @mkdir -p $(abspath $(DIR_NAME)) 58 | @cp -R $(filter-out $(DONT_COPY), $(wildcard *)) $(abspath $(DIR_NAME)) 59 | @echo "\tfuzzylog @ $(abspath ../..)" 60 | ifeq ($(DELOS_RUST_LOC), ) 61 | @echo "run\n\texport DELOS_RUST_LOC=$(abspath ../..)\nto enable linking." 62 | endif 63 | ifeq ($(DELOS_RUST_LOC), ../..) 64 | @echo "run\n\t\033[0;37mexport DELOS_RUST_LOC=$(abspath ../..)\033[0m\nto enable linking." 65 | endif 66 | endif 67 | -------------------------------------------------------------------------------- /examples/c_multi_server/Readme.md: -------------------------------------------------------------------------------- 1 | # C Multi-Server Example 2 | 3 | This example demonstrates the output from the `new_dir` 4 | command from the [c_linking Makefile](../c_linking/Makefile), 5 | as well as starting clients via a config file. 6 | 7 | ## `new_dir` Output. 8 | 9 | The `new_dir` command copies `.gitignore`, `Makefile`, 10 | `Readme.md`, and `start.c` to a new directory. 11 | The Makefile is setup so that it will work from any location 12 | as long as `DELOS_RUST_LOC` is set to a delos-rust directory. 13 | It comes preconfigured to link in the needed system libraries 14 | and the delos-rust library. 15 | 16 | ## Config File 17 | 18 | FuzzyLog servers are replicated using chain replication for 19 | reliability. 20 | The function `new_dag_handle_from_config` can start a dag handle 21 | for a server-group from a config file with the format 22 | 23 | DELOS_CHAIN_SERVERS=":+" 24 | DELOS_CHAIN_SERVERS_TAILS=":+" 25 | 26 | where `DELOS_CHAIN_SERVERS` contains the `:`s of the 27 | heads of the replication chains, and `DELOS_CHAIN_SERVERS_TAILS` are 28 | the ones for the tails of the replication chain. 29 | If for some reason you wish to run without replcation, 30 | `DELOS_CHAIN_SERVERS_TAILS` can be left out. 31 | -------------------------------------------------------------------------------- /examples/c_multi_server/server_config: -------------------------------------------------------------------------------- 1 | DELOS_CHAIN_SERVERS="127.0.0.1:13241 127.0.0.1:13242 127.0.0.1:13243" 2 | 3 | -------------------------------------------------------------------------------- /examples/c_multi_server/start.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "../c_linking/fuzzy_log.h" 6 | 7 | static char out[DELOS_MAX_DATA_SIZE]; 8 | 9 | int main() 10 | { 11 | start_servers_from_config("./server_config"); 12 | 13 | struct colors color = { .numcolors = 3, .mycolors = (ColorID[]){2, 3, 4}}; 14 | struct DAGHandle* dag = new_dag_handle_from_config("./server_config", &color); 15 | printf("fuzzy log client at %p.\n", dag); 16 | 17 | uint32_t data; 18 | { 19 | data = 401; 20 | color.mycolors = (ColorID[]){4, 2}; 21 | color.numcolors = 1; 22 | printf("sending %d to %d.\n", data, color.mycolors[0]); 23 | append(dag, (char *)&data, sizeof(data), &color, NULL); 24 | } 25 | { 26 | data = 102; 27 | color.mycolors = (ColorID[]){2, 3}; 28 | color.numcolors = 1; 29 | printf("sending %d to %d.\n", data, color.mycolors[0]); 30 | append(dag, (char *)&data, sizeof(data), &color, NULL); 31 | } 32 | { 33 | data = 733; 34 | color.mycolors = (ColorID[]){3, 4};; 35 | color.numcolors = 1; 36 | printf("sending %d to %d.\n", data, color.mycolors[0]); 37 | append(dag, (char *)&data, sizeof(data), &color, NULL); 38 | } 39 | uint32_t end_key; 40 | { 41 | srand(time(NULL)); 42 | end_key = rand(); 43 | data = end_key; 44 | color.mycolors = (ColorID[]){2, 3, 4}; 45 | color.numcolors = 3; 46 | printf("sending %d to all.\n", data); 47 | append(dag, (char *)&data, sizeof(data), &color, NULL); 48 | } 49 | 50 | snapshot(dag); 51 | 52 | while (color.numcolors != 0) { 53 | size_t size = 0; 54 | get_next(dag, out, &size, &color); 55 | if (color.numcolors != 0) { 56 | printf("read %zu bytes = %d from", size, *(uint32_t *)out); 57 | for(size_t i = 0; i < color.numcolors; i++) { 58 | printf(" %d", color.mycolors[i]); 59 | } 60 | printf(".\n"); 61 | } 62 | else { 63 | printf("finished reading.\n"); 64 | } 65 | } 66 | 67 | close_dag_handle(dag); 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /examples/hello_c/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | *.rlib 4 | *.a 5 | *.o 6 | out 7 | -------------------------------------------------------------------------------- /examples/hello_c/Makefile: -------------------------------------------------------------------------------- 1 | #USAGE 2 | # 3 | # make [all] builds and links example, placing it in ./out/hello 4 | # 5 | # make rust_code builds the FuzzyLog library in $(FUZZYLOG_SRC_LOC)/target/debug/ 6 | # 7 | # make mostlyclean removes artifacts (object files and binaries) generated from C code 8 | # make rust_clean removes artifacts generated from rust code 9 | # make clean removes all generated artifacts 10 | # 11 | # make new_dir DIR_NAME= 12 | # Creates a new copy of this makefile and necessary code in directory 13 | # such that the above commands will work in said directory 14 | # this relies on the environment variable FUZZYLOG_SRC_LOC being set to the 15 | # location of a local copy of the FuzzyLog repository. 16 | 17 | C_SRC := main.c 18 | 19 | FUZZYLOG_SRC_LOC ?= $(realpath ../..) 20 | 21 | OS_NAME := $(shell uname) 22 | 23 | LINK_FLAGS += -L$(FUZZYLOG_SRC_LOC)/target/debug -lfuzzy_log 24 | 25 | ifeq ($(OS_NAME), Linux) 26 | LINK_FLAGS += -lm -ldl -lrt -pthread -Wl,--gc-sections 27 | else ifeq ($(UNAME_S),Darwin) 28 | LINK_FLAGS += -lsystem -lc -lm -pthread 29 | endif 30 | 31 | CFLAGS += -O2 -std=gnu11 -I$(FUZZYLOG_SRC_LOC) 32 | WFLAGS += -Wall -Wextra -Wpointer-arith -Wundef -Wformat=2 -Wnested-externs -Wno-unused-parameter 33 | 34 | .PHONY: all rust_code clean mostlyclean rust_clean new_dir 35 | 36 | all: out/hello 37 | 38 | out/hello: rust_code $(C_SRC) 39 | @mkdir -p ./out 40 | $(CC) main.c -o ./out/hello $(CFLAGS) $(WFLAGS) $(LINK_FLAGS) 41 | 42 | rust_code: $(FUZZYLOG_SRC_LOC)/target/debug/libc_link.a 43 | 44 | 45 | $(FUZZYLOG_SRC_LOC)/target/debug/libc_link.a: $(shell find $(FUZZYLOG_SRC_LOC)/src/ -type f) 46 | @echo "Building fuzzy log @ $(FUZZYLOG_SRC_LOC)" 47 | @{ cd $(FUZZYLOG_SRC_LOC) && cargo build; } || \ 48 | { echo "\033[0;31mHave you set FUZZYLOG_SRC_LOC?\033[0m" && exit 1; } 49 | 50 | clean: rust_clean mostlyclean 51 | 52 | mostlyclean: 53 | rm -rf ./out 54 | 55 | rust_clean: 56 | @echo "Cleaning $(FUZZYLOG_SRC_LOC)" 57 | @cd $(FUZZYLOG_SRC_LOC) && cargo clean 58 | 59 | DONT_COPY = target out Cargo.lock Cargo.toml src 60 | 61 | new_dir: 62 | ifeq ($(strip $(DIR_NAME)),) 63 | @echo "DIR_NAME must be non-empty" 64 | else 65 | @echo "Setting up in $(abspath $(DIR_NAME))" 66 | @mkdir -p $(abspath $(DIR_NAME)) 67 | @cp -R $(filter-out $(DONT_COPY), $(wildcard *)) $(abspath $(DIR_NAME)) 68 | @echo "\tfuzzylog @ $(abspath ../..)" 69 | ifeq ($(FUZZYLOG_SRC_LOC), ) 70 | @echo "run\n\texport FUZZYLOG_SRC_LOC=$(abspath ../..)\nto enable linking." 71 | endif 72 | ifeq ($(FUZZYLOG_SRC_LOC), ../..) 73 | @echo "run\n\t\033[0;37mexport FUZZYLOG_SRC_LOC=$(abspath ../..)\033[0m\nto enable linking." 74 | endif 75 | endif 76 | -------------------------------------------------------------------------------- /examples/hello_c/Readme.md: -------------------------------------------------------------------------------- 1 | # C Hello World Example 2 | 3 | This directory contains an example of running the FuzzyLog client from C, along 4 | with a Makefile which hopefully makes building such projects simple. For the 5 | rust equivalent see [examples/hello_rust](../hello_rust). 6 | 7 | ## Building the Example 8 | 9 | Make sure you have `rust` intalled (run `curl https://sh.rustup.rs -sSf | sh` if not) 10 | and `make`. 11 | 12 | Running `make` this will output the example binary in `./out/hello`. 13 | This binary is standalone. It starts up its own instance of the 14 | FuzzyLog server at `127.0.0.1:13229` to run against, 15 | starts a client, performs some appends and reads them back. 16 | 17 | ## Starting you own project 18 | 19 | To create your own FuzzyLog project, use the command 20 | 21 | make new_dir DIR_NAME= 22 | 23 | which will copy the relevant files to . 24 | Then set the environment variable `FUZZYLOG_SRC_LOC` to the location of your 25 | local copy of the FuzzyLog source code. 26 | (In the examples folder a simple copy-paste will suffice). 27 | 28 | See [`fuzzylog.h`](../../fuzzylog.h) for the FuzzyLog client C header. 29 | -------------------------------------------------------------------------------- /examples/hello_c/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | * The FuzzyLog client library header provides an intuitive C interface to the 6 | * fuzzy log 7 | */ 8 | #include "fuzzylog.h" 9 | 10 | static void print_events(void *state, const char *data, uintptr_t data_size); 11 | static void count_events(void *state, const char *data, uintptr_t data_size); 12 | 13 | extern void start_fuzzy_log_server_thread(char *); 14 | 15 | static char *local_server_ip = "127.0.0.1:13229"; 16 | 17 | int 18 | main(int argc, char *argv[argc]) 19 | { 20 | ServerSpec servers = { .num_ips = 1, servers.head_ips = &local_server_ip}; 21 | if(argc == 1) { 22 | /* 23 | * This isn't part of the FuzzyLog client, but we start a FuzzyLog server 24 | * on another thread to make this code easy to run 25 | */ 26 | printf("(Running against local server)\n\n"); 27 | start_fuzzy_log_server_thread("0.0.0.0:13229"); 28 | } else { 29 | servers.num_ips = argc - 1; 30 | servers.head_ips = &argv[1]; 31 | } 32 | 33 | printf("First we start a FuzzyLog client... "); 34 | 35 | uint64_t chains[3] = {1ull, 3ull, 7ull}; 36 | ColorSpec my_color = {.local_chain = 1, .remote_chains = chains, .num_remote_chains = 3}; 37 | 38 | FLPtr log = new_fuzzylog_instance(servers, my_color, NULL); 39 | 40 | /* An example of basic FuzzyLog usage. */ 41 | { 42 | printf("FuzzyLog client started @ 0x%p.\n\n", log); 43 | printf("Let's send some data\n"); 44 | 45 | { 46 | uint32_t data = 11; 47 | printf("\tsending %d to my color\n", data); 48 | fuzzylog_append(log, (char *)&data, sizeof(data), &my_color, 1); 49 | } 50 | { 51 | uint32_t data = 12; 52 | printf("\tsending %d to my color\n", data); 53 | fuzzylog_append(log, (char *)&data, sizeof(data), &my_color, 1); 54 | } 55 | { 56 | uint32_t data = 13; 57 | printf("\tsending %d to my color\n", data); 58 | fuzzylog_append(log, (char *)&data, sizeof(data), &my_color, 1); 59 | } 60 | 61 | printf("and now we sync\n"); 62 | 63 | fuzzylog_sync(log, print_events, NULL); 64 | 65 | printf("the sync is done!\n"); 66 | printf("When a single client writes to the log, everything is totally ordered.\n\n"); 67 | } 68 | 69 | /* 70 | * But just running on one log isn't that interesting. 71 | * Let's add some dependencies. We'll need more clients for this. 72 | */ 73 | 74 | printf("Starting a second client, and syncing it with the log.\n"); 75 | ColorSpec my_color2 = {.local_chain = 3, .remote_chains = chains, .num_remote_chains = 3}; 76 | FLPtr second_log = new_fuzzylog_instance(servers, my_color2, NULL); 77 | 78 | printf("Second client started @ %p.\n\n", log); 79 | printf("Second client getting the first client's appends... "); 80 | uint32_t events_seen = 0; 81 | while(events_seen < 3) { 82 | fuzzylog_sync(second_log, count_events, &events_seen); 83 | } 84 | printf("done!\n\n"); 85 | 86 | printf("Since the second client saw all of the first client's events\n"); 87 | printf("all of these new events will be ordered after them.\n"); 88 | { 89 | uint32_t data = 21; 90 | printf("\tsecond client sending %d to my color\n", data); 91 | fuzzylog_append(second_log, (char *)&data, sizeof(data), &my_color2, 1); 92 | } 93 | { 94 | uint32_t data = 22; 95 | printf("\tsending %d to my color\n", data); 96 | fuzzylog_append(second_log, (char *)&data, sizeof(data), &my_color2, 1); 97 | } 98 | { 99 | uint32_t data = 23; 100 | printf("\tsending %d to my color\n", data); 101 | fuzzylog_append(second_log, (char *)&data, sizeof(data), &my_color2, 1); 102 | } 103 | 104 | fuzzylog_close(second_log); 105 | 106 | printf("and clients will see them in that order.\n"); 107 | { 108 | FLPtr reader = new_fuzzylog_instance(servers, my_color, NULL); 109 | for(events_seen = 0; events_seen < 6;) { 110 | fuzzylog_sync(reader, print_events, &events_seen); 111 | } 112 | fuzzylog_close(reader); 113 | } 114 | 115 | printf("However if the original client appends new events without syncing\n"); 116 | { 117 | uint32_t data = 14; 118 | printf("\tfirst client sending %d to my color\n", data); 119 | fuzzylog_append(log, (char *)&data, sizeof(data), &my_color, 1); 120 | } 121 | { 122 | uint32_t data = 15; 123 | printf("\tfirst client sending %d to my color\n", data); 124 | fuzzylog_append(log, (char *)&data, sizeof(data), &my_color, 1); 125 | } 126 | { 127 | uint32_t data = 16; 128 | printf("\tfirst client sending %d to my color\n", data); 129 | fuzzylog_append(log, (char *)&data, sizeof(data), &my_color, 1); 130 | } 131 | 132 | printf("clients can see them in any order with respect to the second clients appends.\n"); 133 | FLPtr reader = new_fuzzylog_instance(servers, my_color, NULL); 134 | for(events_seen = 0; events_seen < 9;) { 135 | fuzzylog_sync(reader, print_events, &events_seen); 136 | } 137 | fuzzylog_close(reader); 138 | 139 | fuzzylog_close(log); 140 | 141 | printf("\n"); 142 | 143 | return 0; 144 | } 145 | 146 | static void 147 | print_events(void *state, const char *data, uintptr_t data_size) { 148 | if(data_size != 4) { 149 | printf("\tUh oh, unexpected data.\n"); 150 | exit(1); 151 | } 152 | 153 | if(state != NULL) *(uint32_t *)state += 1; 154 | 155 | printf("\tread %u from the log\n", *(uint32_t *)data); 156 | 157 | } 158 | 159 | static void 160 | count_events(void *state, const char *data, uintptr_t data_size) { 161 | if(data_size != 4) { 162 | printf("\tUh oh, unexpected data.\n"); 163 | exit(1); 164 | } 165 | 166 | *(uint32_t *)state += 1; 167 | } 168 | 169 | -------------------------------------------------------------------------------- /examples/hello_rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hello_rust" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | fuzzy_log = {path = "../.."} 8 | -------------------------------------------------------------------------------- /examples/hello_rust/Readme.md: -------------------------------------------------------------------------------- 1 | # Rust Hello World Example 2 | 3 | This directory contains a simple example of running the FuzzyLog client from rust. 4 | For the C equivalent see [examples/hello_c](../hello_c). 5 | 6 | ## Building the Example 7 | 8 | Make sure you have `rust` intalled (run `curl https://sh.rustup.rs -sSf | sh` if not) 9 | and `cargo run`. 10 | 11 | This will run the example. It starts up its own instance of the FuzzyLog server 12 | at `127.0.0.1:13229` to run against, starts a client, performs some appends and 13 | reads them back. 14 | -------------------------------------------------------------------------------- /examples/java_proxy/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "java_proxy" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | env_logger = "0.3" 8 | mio = "0.6.6" 9 | byteorder = "1.1.0" 10 | fuzzy_log_client = {path = "../../fuzzy_log_client"} 11 | structopt = "0.0.5" 12 | structopt-derive = "0.0.5" 13 | 14 | [profile.release] 15 | opt-level = 3 16 | debug = true 17 | # debug = false 18 | rpath = false 19 | lto = false 20 | debug-assertions = false 21 | # debug-assertions = true 22 | codegen-units = 1 23 | panic = "abort" 24 | 25 | [features] 26 | print_stats = ["fuzzy_log_client/print_stats"] 27 | -------------------------------------------------------------------------------- /examples/or_set/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "or_set" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | bincode = "0.8.0" 8 | crossbeam-utils = "0.5" 9 | fuzzy_log_client = {path = "../../fuzzy_log_client"} 10 | rand = "0.3" 11 | serde = "1" 12 | serde_derive = "1" 13 | structopt = "0.2" 14 | 15 | [dev-dependencies] 16 | fuzzy_log_server = {path = "../../fuzzy_log_server"} 17 | env_logger = "0.3" 18 | 19 | [features] 20 | print_stats = ["fuzzy_log_client/print_stats"] 21 | -------------------------------------------------------------------------------- /examples/or_set/src/getter.rs: -------------------------------------------------------------------------------- 1 | 2 | use std::sync::atomic::{AtomicBool, AtomicUsize}; 3 | use std::sync::atomic::Ordering::Relaxed; 4 | use std::time::{Duration, Instant}; 5 | 6 | use or_set::OrSet; 7 | 8 | pub fn run(set: &mut OrSet, interval: u64, duration: u64) -> (Vec, Vec) { 9 | let quit = &AtomicBool::new(false); 10 | let num_elapsed = &AtomicUsize::new(0); 11 | ::crossbeam_utils::thread::scope(move |scope| { 12 | let gets_per_snapshot = scope.spawn(move || do_run(set, num_elapsed, quit)); 13 | let samples = do_measurement(interval, duration, num_elapsed, quit); 14 | (samples, gets_per_snapshot.join().unwrap()) 15 | }) 16 | } 17 | 18 | fn do_run(set: &mut OrSet, num_elapsed: &AtomicUsize, quit: &AtomicBool) -> Vec { 19 | let mut gets_per_snapshot = vec![]; 20 | let mut local_num_elapsed = 0; 21 | while !quit.load(Relaxed) { 22 | let gets = set.get_remote(); 23 | local_num_elapsed += gets; 24 | num_elapsed.store(local_num_elapsed, Relaxed); 25 | gets_per_snapshot.push(gets as u64); 26 | } 27 | gets_per_snapshot 28 | } 29 | 30 | fn do_measurement(interval: u64, duration: u64, num_elapsed: &AtomicUsize, quit: &AtomicBool) 31 | -> Vec { 32 | let mut samples = Vec::with_capacity((duration / interval) as usize); 33 | let mut prev = 0; 34 | let end_time = Instant::now() + Duration::from_secs(duration); 35 | while Instant::now() < end_time { 36 | ::std::thread::sleep(Duration::from_secs(interval)); 37 | let cur = num_elapsed.load(Relaxed); 38 | samples.push((cur - prev) as f64 / interval as f64); 39 | prev = cur; 40 | } 41 | samples 42 | } 43 | -------------------------------------------------------------------------------- /examples/redblue/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "redblue" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | bincode = "0.8.0" 8 | fuzzy_log_client = {path = "../../fuzzy_log_client"} 9 | serde = "1" 10 | serde_derive = "1" 11 | 12 | [dev-dependencies] 13 | fuzzy_log_server = {path = "../../fuzzy_log_server"} 14 | matches = "0.1.6" 15 | env_logger = "0.3" 16 | -------------------------------------------------------------------------------- /examples/simple_map/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "simple_map" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | bincode = "0.8.0" 8 | fuzzy_log_client = {path = "../../fuzzy_log_client"} 9 | serde = "1" 10 | serde_derive = "1" 11 | 12 | [dev-dependencies] 13 | fuzzy_log_server = {path = "../../fuzzy_log_server"} 14 | -------------------------------------------------------------------------------- /examples/simple_map/src/lib.rs: -------------------------------------------------------------------------------- 1 | 2 | extern crate bincode; 3 | extern crate fuzzy_log_client; 4 | 5 | pub extern crate serde; 6 | 7 | #[macro_use] extern crate serde_derive; 8 | 9 | use bincode::{ 10 | deserialize, 11 | serialize, 12 | }; 13 | 14 | use std::{ 15 | collections::HashMap, 16 | hash::Hash, 17 | }; 18 | 19 | use serde::{ 20 | Deserialize, 21 | Serialize, 22 | }; 23 | 24 | pub use fuzzy_log_client::{ 25 | LogHandle, order, 26 | }; 27 | 28 | #[cfg(test)] 29 | mod tests; 30 | 31 | pub struct Map { 32 | 33 | // The Map contains a handle for the fuzzy log. 34 | log: LogHandle<[u8]>, 35 | 36 | // a local view to allow the the map materializing the logs' state 37 | local_view: HashMap, 38 | 39 | // which partition we write to 40 | append_to: order, 41 | } 42 | 43 | #[derive(Debug, Serialize, Deserialize)] 44 | enum Op { 45 | Put(K, V), 46 | Rem(K), 47 | PutOnNotFound(K, V), 48 | } 49 | 50 | impl Map 51 | where 52 | K: Serialize + for<'de> Deserialize<'de> + Hash + Eq, 53 | V: Serialize + for<'de> Deserialize<'de>, { 54 | 55 | pub fn put(&mut self, key: &K, val: &V) { 56 | // To insert an entry into the map we simply append the mutation to the log 57 | // and wait for the append to be completed. 58 | let _ = self.log.simple_append( 59 | &Op::Put(key, val).serialize(), 60 | &mut [self.append_to] 61 | ); 62 | // Since this API doesn't return a value, we don't need to play the log. 63 | } 64 | 65 | pub fn get(&mut self, key: &K) -> Option<&mut V> { 66 | // To read a value from the map, we first synchronize out local view 67 | // with the log 68 | self.sync(); 69 | // after which we return the value form our local view 70 | self.get_cached(key) 71 | } 72 | 73 | pub fn get_cached(&mut self, key: &K) -> Option<&mut V> { 74 | // We can also return query results based on our cached copy of the 75 | // datatstructure. 76 | // This is much faster, but not linearizable. 77 | self.local_view.get_mut(key) 78 | } 79 | 80 | pub fn put_on_not_found(&mut self, key: &K, val: &V) { 81 | let _ = self.log.simple_append( 82 | &Op::PutOnNotFound(key, val).serialize(), 83 | &mut [self.append_to] 84 | ); 85 | } 86 | 87 | pub fn remove(&mut self, key: &K) { 88 | let _ = self.log.simple_append( 89 | &Op::Rem::<_, V>(key).serialize(), 90 | &mut [self.append_to] 91 | ); 92 | } 93 | 94 | pub fn contains_key(&mut self, key: &K) -> bool { 95 | self.sync(); 96 | self.get(key).is_some() 97 | } 98 | 99 | fn sync(&mut self) { 100 | let local_view = &mut self.local_view; 101 | let _ = self.log.sync_events(|e| update_local(local_view, e.data)); 102 | } 103 | 104 | // In a more realistic setting we would most likely wish to perform 105 | // multiple queries at a time using the LogHandle's async_* APIs. 106 | } 107 | 108 | fn update_local(local_view: &mut HashMap, data: &[u8]) 109 | where 110 | K: for<'de> Deserialize<'de> + Hash + Eq, 111 | V: for<'de> Deserialize<'de>, { 112 | match deserialize(data).unwrap() { 113 | Op::Put(key, val) => { local_view.insert(key, val); }, 114 | Op::Rem(key) => { local_view.remove(&key); }, 115 | Op::PutOnNotFound(key, val) => { 116 | local_view.entry(key).or_insert(val); 117 | }, 118 | } 119 | } 120 | 121 | impl Map 122 | where K: Hash + Eq { 123 | pub fn from_log_handle(log: LogHandle<[u8]>, append_to: order) -> Self { 124 | (log, append_to).into() 125 | } 126 | } 127 | 128 | impl From<(LogHandle<[u8]>, order)> for Map 129 | where K: Hash + Eq { 130 | fn from((log, append_to): (LogHandle<[u8]>, order)) -> Self { 131 | Self { 132 | log, 133 | local_view: HashMap::default(), 134 | append_to, 135 | } 136 | } 137 | } 138 | 139 | 140 | impl Op { 141 | fn serialize(&self) -> Vec 142 | where 143 | K: Serialize, 144 | V: Serialize, { 145 | serialize(self, bincode::Infinite).unwrap() 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /examples/simple_map/src/tests.rs: -------------------------------------------------------------------------------- 1 | // Test code for the map example. 2 | 3 | extern crate fuzzy_log_server; 4 | 5 | use std::{ 6 | net::SocketAddr, 7 | sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}, 8 | thread, 9 | }; 10 | 11 | use ::*; 12 | 13 | use tests::fuzzy_log_server::tcp::run_server; 14 | 15 | #[test] 16 | fn one_column_unshared_map() { 17 | static STARTED: AtomicUsize = ATOMIC_USIZE_INIT; 18 | thread::spawn(|| { 19 | print!("starting server..."); 20 | run_server( 21 | "127.0.0.1:8223".parse().unwrap(), 0, 1, None, None, 1, &STARTED) 22 | }); 23 | 24 | while STARTED.load(Ordering::Relaxed) == 0 { 25 | thread::yield_now() 26 | } 27 | 28 | println!(" done."); 29 | 30 | println!("Running a single column Map"); 31 | let addr: SocketAddr = "127.0.0.1:8223".parse().unwrap(); 32 | let handle = LogHandle::unreplicated_with_servers(Some(addr)) 33 | .my_colors_chains(Some(1.into())) 34 | .reads_my_writes() 35 | .build(); 36 | let mut map: Map<_, _> = (handle, order::from(1)).into(); 37 | 38 | println!("puting {:?} => {:?}", 333, 124); 39 | map.put(&333, &124); 40 | 41 | println!("puting {:?} => {:?}", 3, 42); 42 | map.put(&3, &42); 43 | 44 | println!("puting {:?} => {:?}", 651, 0); 45 | map.put(&651, &0); 46 | 47 | println!("puting {:?} => {:?}", 1, 2); 48 | map.put(&1, &2); 49 | 50 | println!("cached value for {:3?} is {:?}", 333, map.get_cached(&333)); 51 | assert_eq!(map.get_cached(&333), None); 52 | println!("cached value for {:3?} is {:?}", 3, map.get_cached(&3)); 53 | assert_eq!(map.get_cached(&3), None); 54 | println!("cached value for {:3?} is {:?}", 651, map.get_cached(&651)); 55 | assert_eq!(map.get_cached(&651), None); 56 | println!("cached value for {:3?} is {:?}", 1, map.get_cached(&1)); 57 | assert_eq!(map.get_cached(&1), None); 58 | println!("cached value for {:3?} is {:?}", 1, map.get_cached(&1000)); 59 | assert_eq!(map.get_cached(&1000), None); 60 | 61 | println!("reading {:?}", 651); 62 | assert_eq!(map.get(&651), Some(&mut 0)); 63 | 64 | println!("cached value for {:3?} is {:?}", 333, map.get_cached(&333)); 65 | assert_eq!(map.get_cached(&333), Some(&mut 124)); 66 | println!("cached value for {:3?} is {:?}", 3, map.get_cached(&3)); 67 | assert_eq!(map.get_cached(&3), Some(&mut 42)); 68 | println!("cached value for {:3?} is {:?}", 651, map.get_cached(&651)); 69 | assert_eq!(map.get_cached(&651), Some(&mut 0)); 70 | println!("cached value for {:3?} is {:?}", 1, map.get_cached(&1)); 71 | assert_eq!(map.get_cached(&1), Some(&mut 2)); 72 | println!("cached value for {:3?} is {:?}", 1, map.get_cached(&1000)); 73 | assert_eq!(map.get_cached(&1000), None); 74 | } 75 | -------------------------------------------------------------------------------- /examples/zookeeper/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "zookeeper" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | bincode = "0.8.0" 8 | fuzzy_log_client = {path = "../../fuzzy_log_client"} 9 | matches = "0.1.6" 10 | serde = "1" 11 | serde_derive = "1" 12 | 13 | [dev-dependencies] 14 | fuzzy_log_server = {path = "../../fuzzy_log_server"} 15 | env_logger = "0.3" 16 | 17 | [features] 18 | print_stats = ["fuzzy_log_client/print_stats"] 19 | -------------------------------------------------------------------------------- /examples/zookeeper/benches/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate test; 4 | 5 | extern crate zookeeper; 6 | 7 | use std::collections::HashMap; 8 | 9 | use test::{black_box, Bencher}; 10 | 11 | use zookeeper::files::FileSystem; 12 | use zookeeper::WhichPath; 13 | use zookeeper::message::{self, CreateMode, Id}; 14 | use zookeeper::message::Mutation::*; 15 | 16 | #[bench] 17 | pub fn create(b: &mut Bencher) { 18 | message::set_client_id(101); 19 | let my_root = "/abcd/".into(); 20 | let mut roots = HashMap::new(); 21 | roots.insert("abcd".into(), 101.into()); 22 | let mut files = FileSystem::new(my_root, roots); 23 | let mut i = 0u64; 24 | b.iter(|| { 25 | files.apply_mutation( 26 | Create { 27 | id: Id::new(), 28 | create_mode: CreateMode::persistent(), 29 | path: format!("/abcd/{}", i).into(), 30 | data: vec![0, 1, 2, i as u8], 31 | }, 32 | WhichPath::Path1, 33 | |id, r, m0, m1| { 34 | black_box((id, r, m0, m1)); 35 | i += 1 36 | }, 37 | ); 38 | }) 39 | } 40 | 41 | #[bench] 42 | pub fn create_rename(b: &mut Bencher) { 43 | let my_root = "/abcd/".into(); 44 | let mut roots = HashMap::new(); 45 | roots.insert("abcd".into(), 101.into()); 46 | let mut files = FileSystem::new(my_root, roots); 47 | let mut i = 0u64; 48 | b.iter(|| { 49 | files.apply_mutation( 50 | Create { 51 | id: Id::new(), 52 | create_mode: CreateMode::persistent(), 53 | path: format!("/abcd/{}", i).into(), 54 | data: vec![0, 1, 2, i as u8], 55 | }, 56 | WhichPath::Path1, 57 | |id, r, m0, m1| { 58 | black_box((id, r, m0, m1)); 59 | }, 60 | ); 61 | let rename_id = Id::new(); 62 | files.apply_mutation( 63 | RenamePart1 { 64 | id: rename_id, 65 | old_path: format!("/abcd/{}", i).into(), 66 | new_path: format!("/abcd/{}_{}", i, i).into(), 67 | }, 68 | WhichPath::Both, 69 | |id, r, m0, m1| { 70 | black_box((id, r, m0, m1)); 71 | }, 72 | ); 73 | files.apply_mutation( 74 | RenameNewEmpty { 75 | id: Id::new(), 76 | part1_id: rename_id, 77 | old_path: format!("/abcd/{}", i).into(), 78 | new_path: format!("/abcd/{}_{}", i, i).into(), 79 | }, 80 | WhichPath::Both, 81 | |id, r, m0, m1| { 82 | black_box((id, r, m0, m1)); 83 | }, 84 | ); 85 | files.apply_mutation( 86 | RenameOldExists { 87 | id: Id::new(), 88 | create_mode: CreateMode::persistent(), 89 | data: vec![0, 1, 2, i as u8], 90 | part1_id: rename_id, 91 | old_path: format!("/abcd/{}", i).into(), 92 | new_path: format!("/abcd/{}_{}", i, i).into(), 93 | }, 94 | WhichPath::Both, 95 | |id, r, m0, m1| { 96 | black_box((id, r, m0, m1)); 97 | }, 98 | ); 99 | i += 1; 100 | }) 101 | } 102 | -------------------------------------------------------------------------------- /examples/zookeeper/filter.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | 3 | array = [ 4 | 3081186, 5 | 2321230, 6 | 2061901, 7 | 1638528, 8 | 737546, 9 | 1106974, 10 | 297181, 11 | 609149, 12 | 216574, 13 | 345637, 14 | 4069959, 15 | 1267186, 16 | 2578993, 17 | 1175917, 18 | 737942, 19 | 1070143, 20 | 266270, 21 | 734787, 22 | 282598, 23 | 386876, 24 | 434618, 25 | 756617, 26 | 360364, 27 | 658804, 28 | 283607, 29 | 528643, 30 | 214238, 31 | 356830, 32 | 119026, 33 | 98111, 34 | 524433, 35 | 547037, 36 | 326763, 37 | 559806, 38 | 266205, 39 | 542412, 40 | 179787, 41 | 385465, 42 | 89563, 43 | 191446 44 | ] 45 | 46 | reads = [] 47 | writes = [] 48 | 49 | for i in range(0, len(array), 2): 50 | reads.append(array[i]) 51 | writes.append(array[i+1]) 52 | 53 | read_str = '' 54 | write_str = '' 55 | for row in range(0, 5): 56 | for col in range(0, 4): 57 | read_str += '{:>7}'.format(reads[row + 5 * col]) + ' ' 58 | write_str += '{:>7}'.format(writes[row + 5 * col]) + ' ' 59 | 60 | read_str += '\n' 61 | write_str += '\n' 62 | 63 | print('reads') 64 | print(str(read_str)) 65 | print('writes') 66 | print(str(write_str)) 67 | -------------------------------------------------------------------------------- /examples/zookeeper/get_ips.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | import boto3 3 | 4 | ec2client = boto3.client('ec2') 5 | response = ec2client.describe_instances() 6 | public_dns = [] 7 | private_ip = [] 8 | clients = [] 9 | servers = [] 10 | for reservation in response["Reservations"]: 11 | for instance in reservation["Instances"]: 12 | if instance[u'PublicDnsName'] != "": 13 | public_dns.append(instance[u'PublicDnsName']) 14 | private_ip.append(instance[u'PrivateIpAddress']) 15 | 16 | num_instances = len(private_ip) 17 | print(num_instances) 18 | num_clients = len(public_dns) - 6 19 | num_views = 8 20 | 21 | all_hosts = "" 22 | for host in public_dns: 23 | all_hosts = all_hosts + host + "," 24 | 25 | print(all_hosts) 26 | 27 | print(public_dns) 28 | print(len(public_dns)) 29 | print("") 30 | print("") 31 | 32 | print("clients") 33 | print(public_dns[0:num_clients]) 34 | print(private_ip[0:num_views]) 35 | view_names = private_ip[0] + ":13333" 36 | for name in private_ip[1:num_views]: 37 | view_names += "^" + name + ":13333" 38 | print(view_names) 39 | print("") 40 | 41 | print("Views") 42 | 43 | print("") 44 | 45 | print("Servers") 46 | print(public_dns[num_clients:]) 47 | server_names = "" 48 | print(private_ip[num_clients:]) 49 | for name in public_dns[num_clients:]: 50 | server_names = server_names + name + "," 51 | print(server_names) 52 | 53 | -------------------------------------------------------------------------------- /examples/zookeeper/tester/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "zk_test" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | crossbeam = "0.2.10" 8 | rand = "0.4" 9 | structopt = "0.0.5" 10 | structopt-derive = "0.0.5" 11 | zipf = "1.1.0" 12 | zookeeper = {path = ".."} 13 | 14 | [features] 15 | print_stats = ["zookeeper/print_stats"] 16 | 17 | [profile.release] 18 | opt-level = 3 19 | # debug = true 20 | debug = false 21 | rpath = false 22 | lto = false 23 | debug-assertions = false 24 | codegen-units = 1 25 | panic = "abort" 26 | # panic = "unwind" 27 | -------------------------------------------------------------------------------- /examples/zookeeper/tester/read_experiment.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | 3 | import os 4 | import subprocess 5 | import sys 6 | import time 7 | 8 | def run(transaction_in=0, two_replica_sets=True, one_chain=False): 9 | server_ip = None 10 | server_hostnames = None 11 | ips = None 12 | if two_replica_sets: 13 | server_ip = '172.31.5.245:13289#172.31.3.165:13289^172.31.6.77:13289#172.31.9.164:13289' 14 | 15 | ips = '172.31.5.245#172.31.0.84#172.31.3.165^172.31.6.77#172.31.4.131#172.31.9.164' 16 | 17 | server_hostnames = 'ec2-34-227-59-97.compute-1.amazonaws.com,ec2-54-164-153-29.compute-1.amazonaws.com,ec2-52-200-149-228.compute-1.amazonaws.com,ec2-54-144-230-60.compute-1.amazonaws.com,ec2-54-89-227-88.compute-1.amazonaws.com,ec2-34-228-61-79.compute-1.amazonaws.com' 18 | 19 | else: 20 | server_ip = '172.31.5.245:13289#172.31.3.165:13289' 21 | 22 | ips = '172.31.5.245#172.31.0.84#172.31.3.165' 23 | 24 | server_hostnames = 'ec2-34-227-59-97.compute-1.amazonaws.com,ec2-54-164-153-29.compute-1.amazonaws.com,ec2-52-200-149-228.compute-1.amazonaws.com' 25 | 26 | 27 | client_hostnames = ['ec2-54-221-13-117.compute-1.amazonaws.com', 'ec2-54-165-98-109.compute-1.amazonaws.com', 'ec2-54-210-182-177.compute-1.amazonaws.com', 'ec2-54-88-115-132.compute-1.amazonaws.com', 'ec2-54-175-66-27.compute-1.amazonaws.com', 'ec2-75-101-219-163.compute-1.amazonaws.com', 'ec2-34-207-59-99.compute-1.amazonaws.com', 'ec2-35-173-248-72.compute-1.amazonaws.com', 'ec2-34-229-218-220.compute-1.amazonaws.com', 'ec2-54-209-50-54.compute-1.amazonaws.com', 'ec2-34-234-77-217.compute-1.amazonaws.com', 'ec2-54-197-0-246.compute-1.amazonaws.com', 'ec2-54-164-4-121.compute-1.amazonaws.com', 'ec2-52-90-95-241.compute-1.amazonaws.com'] 28 | 29 | print(len(client_hostnames)) 30 | 31 | clients = client_hostnames[0] 32 | for client in client_hostnames[1:]: 33 | clients += ',' + client 34 | 35 | for i in [8]: 36 | print("run " + str(i)) 37 | 38 | command = "run_chain:chain_hosts=" + ips 39 | 40 | s = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", 41 | server_hostnames, command]) 42 | 43 | time.sleep(3) 44 | 45 | ######################################## 46 | 47 | command = 'mirror:pkill zk_test; cd examples/zookeeper/tester/ &&' + \ 48 | ' cargo run --release --' + \ 49 | ' ' + server_ip + \ 50 | ' #server_num' + \ 51 | ' ' + str(i) + \ 52 | ' ' + str(750) 53 | 54 | if transaction_in != 0: 55 | command += ' -t ' + str(transaction_in) 56 | 57 | if one_chain: 58 | command += ' -o ' 59 | 60 | v = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", clients, 61 | command]) 62 | 63 | # time.sleep(1) 64 | 65 | ######################################## 66 | 67 | # command = 'mirror:pkill traffic_gen; cd examples/zookeeper/traffic_gen/ &&' +\ 68 | # ' cargo run --release --' +\ 69 | # ' write ' + server_ip 70 | 71 | #w = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", write_host, 72 | # command]) 73 | 74 | ######################################## 75 | 76 | # rs = [] 77 | # num = 0 78 | # print(client_hostnames[:i]) 79 | # for client in client_hostnames[:i]: 80 | # command = 'mirror:pkill traffic_gen; cd examples/zookeeper/traffic_gen/ &&' +\ 81 | # ' cargo run --release --' +\ 82 | # ' read ' + str(num) + ' ' + view_ip[num] + ":" + str(socket) + ' ' + str(3) + ' ' + str(500) 83 | # num += 1 84 | 85 | # r = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", client, 86 | # command]) 87 | # rs.append(r) 88 | 89 | # for r in rs: 90 | # r.wait() 91 | 92 | #w.wait() 93 | v.wait() 94 | s.kill() 95 | 96 | print("") 97 | print("> ") 98 | print("========================================") 99 | print("> ----------------------------------------") 100 | print("========================================") 101 | print("> ") 102 | print("") 103 | sys.stdout.flush() 104 | 105 | subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", server_hostnames, "kill_server"]) 106 | 107 | subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", clients, 108 | 'mirror:pkill zkv']) 109 | 110 | 111 | os.chdir('../../..') 112 | 113 | # run(0, False, True) 114 | # exit(0) 115 | 116 | for one_chain in [False, True]: # 117 | if one_chain: 118 | print("> color per server") 119 | else: 120 | print("> color per view") 121 | 122 | for two_replica_sets in [True, False]: 123 | 124 | if two_replica_sets: 125 | print("> 2 replica sets") 126 | else: 127 | print("> 1 replica sets") 128 | 129 | for transaction_in in [0, 1000, 100, 10, 1]: 130 | if transaction_in == 0: 131 | print("> 0%") 132 | else: 133 | print("> " + str(100.0 / transaction_in) + "%") 134 | 135 | sys.stdout.flush() 136 | run(transaction_in, two_replica_sets, one_chain) 137 | -------------------------------------------------------------------------------- /examples/zookeeper/tester/run_experiment.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python 2 | 3 | import os 4 | import subprocess 5 | import sys 6 | import time 7 | 8 | server_ip = '172.31.5.245:13289#172.31.3.165:13289^172.31.6.77:13289#172.31.9.164:13289' 9 | # server_ip = '172.31.5.245:13289#172.31.3.165:13289' 10 | # server_ip = '172.31.6.77:13289#172.31.9.164:13289' 11 | client_hostnames = ['ec2-52-207-225-244.compute-1.amazonaws.com', 'ec2-54-86-151-248.compute-1.amazonaws.com', 'ec2-54-172-94-178.compute-1.amazonaws.com', 'ec2-54-89-191-5.compute-1.amazonaws.com', 'ec2-54-175-235-70.compute-1.amazonaws.com', 'ec2-34-228-74-217.compute-1.amazonaws.com', 'ec2-18-232-149-155.compute-1.amazonaws.com', 'ec2-184-73-129-248.compute-1.amazonaws.com', 'ec2-54-84-172-42.compute-1.amazonaws.com', 'ec2-54-85-153-64.compute-1.amazonaws.com', 'ec2-54-166-208-238.compute-1.amazonaws.com', 'ec2-107-22-156-190.compute-1.amazonaws.com', 'ec2-52-204-151-151.compute-1.amazonaws.com', 'ec2-34-235-88-94.compute-1.amazonaws.com'] 12 | 13 | server_hostnames = 'ec2-34-229-215-103.compute-1.amazonaws.com,ec2-54-196-154-185.compute-1.amazonaws.com,ec2-18-232-182-64.compute-1.amazonaws.com,ec2-174-129-48-72.compute-1.amazonaws.com,ec2-54-209-214-144.compute-1.amazonaws.com,ec2-34-227-61-64.compute-1.amazonaws.com' 14 | 15 | ips = '172.31.5.245#172.31.0.84#172.31.3.165^172.31.6.77#172.31.4.131#172.31.9.164' 16 | # ips = '172.31.5.245#172.31.0.84#172.31.3.165' 17 | # ips = '172.31.6.77#172.31.4.131#172.31.9.164' 18 | 19 | 20 | num_handles = len(client_hostnames) 21 | 22 | os.chdir('../../..') 23 | 24 | for i in [0]: #range(0, 14): #range(0, 14, 2): #[5, 0, 2]: #range(0, 6): 25 | print("run " + str(i)) 26 | 27 | # command = "run_chain:chain_hosts=" + ips + ",trace=fuzzy_log" 28 | command = "run_chain:chain_hosts=" + ips + ",nt=t"#",trace=fuzzy_log_server"#,debug=t"#,stats=t" 29 | print(command) 30 | p0 = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", server_hostnames, command]) 31 | 32 | 33 | ######################################## 34 | 35 | 36 | command = 'mirror:pkill zk_test; cd examples/zookeeper/tester/ && RUST_BACKTRACE\=short RUSTFLAGS\="-C target-cpu\=native" cargo run --release --' + \ 37 | ' ' + server_ip + \ 38 | ' #server_num' + \ 39 | ' ' + str(num_handles - i) + \ 40 | ' ' + str(100) 41 | print(command) 42 | 43 | client_hoststring = "" 44 | for name in client_hostnames[i:-1]: 45 | client_hoststring += name + "," 46 | client_hoststring += client_hostnames[-1] 47 | 48 | time.sleep(5) 49 | 50 | p1 = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", client_hoststring, 51 | command]) 52 | 53 | p1.wait() 54 | 55 | p0.kill() 56 | 57 | print("") 58 | print("> ") 59 | print("========================================") 60 | print("> ----------------------------------------") 61 | print("========================================") 62 | print("> ") 63 | print("") 64 | sys.stdout.flush() 65 | 66 | p0 = subprocess.Popen(["fab", "-f", "./mirror_on_servers.py", "-H", server_hostnames, "kill_server"]) 67 | -------------------------------------------------------------------------------- /examples/zookeeper/traffic_gen/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "traffic_gen" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | # bincode = "0.8.0" 8 | mio = "0.6.6" 9 | structopt = "0.2" 10 | structopt-derive = "0.2" 11 | zk_view = {path = "../view"} 12 | reactor = {path = "../../../reactor"} 13 | -------------------------------------------------------------------------------- /examples/zookeeper/traffic_gen/run_experiment.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | 3 | import os 4 | import subprocess 5 | import sys 6 | import time 7 | 8 | server_ip = '172.31.5.245:13289#172.31.3.165:13289^172.31.6.77:13289#172.31.9.164:13289' 9 | # server_ip = '172.31.5.245:13289#172.31.3.165:13289' 10 | # server_ip = '172.31.6.77:13289#172.31.9.164:13289' 11 | client_hostnames = ['ec2-52-207-225-244.compute-1.amazonaws.com', 'ec2-54-86-151-248.compute-1.amazonaws.com', 'ec2-54-172-94-178.compute-1.amazonaws.com', 'ec2-54-89-191-5.compute-1.amazonaws.com', 'ec2-54-175-235-70.compute-1.amazonaws.com', 'ec2-34-228-74-217.compute-1.amazonaws.com', 'ec2-18-232-149-155.compute-1.amazonaws.com', 'ec2-184-73-129-248.compute-1.amazonaws.com', 'ec2-54-84-172-42.compute-1.amazonaws.com', 'ec2-54-85-153-64.compute-1.amazonaws.com', 'ec2-54-166-208-238.compute-1.amazonaws.com', 'ec2-107-22-156-190.compute-1.amazonaws.com', 'ec2-52-204-151-151.compute-1.amazonaws.com', 'ec2-34-235-88-94.compute-1.amazonaws.com'] 12 | 13 | server_hostnames = 'ec2-34-229-215-103.compute-1.amazonaws.com,ec2-54-196-154-185.compute-1.amazonaws.com,ec2-18-232-182-64.compute-1.amazonaws.com,ec2-174-129-48-72.compute-1.amazonaws.com,ec2-54-209-214-144.compute-1.amazonaws.com,ec2-34-227-61-64.compute-1.amazonaws.com' 14 | 15 | ips = '172.31.5.245#172.31.0.84#172.31.3.165^172.31.6.77#172.31.4.131#172.31.9.164' 16 | # ips = '172.31.5.245#172.31.0.84#172.31.3.165' 17 | # ips = '172.31.6.77#172.31.4.131#172.31.9.164' 18 | 19 | 20 | num_handles = len(client_hostnames) 21 | 22 | os.chdir('../../..') 23 | 24 | for i in [0]: #range(0, 14): #range(0, 14, 2): #[5, 0, 2]: #range(0, 6): 25 | print("run " + str(i)) 26 | 27 | # command = "run_chain:chain_hosts=" + ips + ",trace=fuzzy_log" 28 | command = "run_chain:chain_hosts=" + ips + ",nt=t"#",trace=fuzzy_log_server"#,debug=t"#,stats=t" 29 | print(command) 30 | p0 = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", server_hostnames, command]) 31 | 32 | 33 | ######################################## 34 | 35 | 36 | command = 'mirror:pkill zk_test; cd examples/zookeeper/tester/ && RUST_BACKTRACE\=short RUSTFLAGS\="-C target-cpu\=native" cargo run --release --' + \ 37 | ' ' + server_ip + \ 38 | ' #server_num' + \ 39 | ' ' + str(num_handles - i) + \ 40 | ' ' + str(100) 41 | print(command) 42 | 43 | client_hoststring = "" 44 | for name in client_hostnames[i:-1]: 45 | client_hoststring += name + "," 46 | client_hoststring += client_hostnames[-1] 47 | 48 | time.sleep(5) 49 | 50 | p1 = subprocess.Popen(["fab", "-f", "./scripts/mirror_on_servers.py", "-H", client_hoststring, 51 | command]) 52 | 53 | p1.wait() 54 | 55 | p0.kill() 56 | 57 | print("") 58 | print("> ") 59 | print("========================================") 60 | print("> ----------------------------------------") 61 | print("========================================") 62 | print("> ") 63 | print("") 64 | sys.stdout.flush() 65 | 66 | p0 = subprocess.Popen(["fab", "-f", "./mirror_on_servers.py", "-H", server_hostnames, "kill_server"]) 67 | -------------------------------------------------------------------------------- /examples/zookeeper/view/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "zk_view" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | bincode = "0.8.0" 8 | mio = "0.6.6" 9 | serde = "1" 10 | serde_derive = "1" 11 | structopt = "0.0.5" 12 | structopt-derive = "0.0.5" 13 | zookeeper = {path = ".."} 14 | reactor = {path = "../../../reactor"} 15 | 16 | [dev-dependencies] 17 | fuzzy_log_server = {path = "../../../fuzzy_log_server"} 18 | 19 | [features] 20 | print_stats = ["zookeeper/print_stats"] 21 | 22 | [profile.release] 23 | opt-level = 3 24 | # debug = true 25 | debug = false 26 | rpath = false 27 | lto = false 28 | debug-assertions = false 29 | codegen-units = 1 30 | panic = "abort" 31 | # panic = "unwind" 32 | -------------------------------------------------------------------------------- /examples/zookeeper/view/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub extern crate bincode; 2 | // extern crate mio; 3 | // extern crate reactor; 4 | pub extern crate serde; 5 | pub extern crate zookeeper; 6 | 7 | #[macro_use] extern crate serde_derive; 8 | 9 | use std::net::SocketAddr; 10 | use std::str::FromStr; 11 | 12 | mod msg; 13 | 14 | pub use msg::*; 15 | 16 | #[derive(Debug, Clone)] 17 | pub struct ServerAddrs(pub Vec<(SocketAddr, SocketAddr)>); 18 | 19 | impl FromStr for ServerAddrs { 20 | type Err = std::string::ParseError; 21 | fn from_str(s: &str) -> Result { 22 | println!("{}", s); 23 | Ok(ServerAddrs( 24 | s.split('^').map(|t|{ 25 | let mut addrs = t.split('#').map(|s| { 26 | match SocketAddr::from_str(s) { 27 | Ok(addr) => addr, 28 | Err(e) => panic!("head parse err {} @ {}", e, s), 29 | } 30 | }); 31 | let head = addrs.next().expect("no head"); 32 | let tail = if let Some(addr) = addrs.next() { 33 | addr 34 | } else { 35 | head 36 | }; 37 | assert!(addrs.next().is_none()); 38 | (head, tail) 39 | }).collect() 40 | )) 41 | } 42 | } 43 | 44 | impl From> for ServerAddrs { 45 | fn from(v: Vec<(SocketAddr, SocketAddr)>) -> Self { 46 | ServerAddrs(v) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /examples/zookeeper/view/src/msg.rs: -------------------------------------------------------------------------------- 1 | 2 | use std::borrow::Cow; 3 | 4 | use zookeeper::{CreateMode, Version, Stat}; 5 | 6 | pub type Id = u64; 7 | 8 | #[derive(Debug, Serialize, Deserialize)] 9 | pub enum Request<'s> { 10 | Create { 11 | id: Id, 12 | path: Cow<'s, str>, 13 | data: Vec, 14 | create_mode: CreateMode, 15 | }, 16 | 17 | Delete { 18 | id: Id, 19 | path: Cow<'s, str>, 20 | version: Version, 21 | }, 22 | 23 | SetData { 24 | id: Id, 25 | path: Cow<'s, str>, 26 | data: Vec, 27 | version: Version, 28 | }, 29 | 30 | // Rename { 31 | // oldPath: Cow<'s, str>, 32 | // newPath: Cow<'s, str>, 33 | // }, 34 | 35 | Exists(Id, Cow<'s, str>), 36 | GetData(Id, Cow<'s, str>), 37 | GetChildren(Id, Cow<'s, str>), 38 | Done, 39 | } 40 | 41 | #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] 42 | pub enum Response { 43 | Ok(Id, String, Vec, Stat, Vec), 44 | Err, 45 | } 46 | -------------------------------------------------------------------------------- /examples/zookeeper/view2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "zkv" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | bincode = "0.8.0" 8 | mio = "0.6.6" 9 | serde = "1" 10 | serde_derive = "1" 11 | structopt = "0.2" 12 | structopt-derive = "0.2" 13 | rand = "0.4" 14 | reactor = {path = "../../../reactor"} 15 | zk_view = {path = "../view"} 16 | zookeeper = {path = ".."} 17 | 18 | [dev-dependencies] 19 | fuzzy_log_server = {path = "../../../fuzzy_log_server"} 20 | 21 | [features] 22 | print_stats = ["zookeeper/print_stats"] 23 | 24 | [profile.release] 25 | opt-level = 3 26 | # debug = true 27 | debug = false 28 | rpath = false 29 | lto = false 30 | debug-assertions = false 31 | codegen-units = 1 32 | panic = "abort" 33 | # panic = "unwind" 34 | -------------------------------------------------------------------------------- /examples/zookeeper/view2/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub extern crate bincode; 2 | // extern crate mio; 3 | // extern crate reactor; 4 | pub extern crate serde; 5 | pub extern crate zookeeper; 6 | 7 | #[macro_use] extern crate serde_derive; 8 | 9 | use std::net::SocketAddr; 10 | use std::str::FromStr; 11 | 12 | mod msg; 13 | 14 | pub use msg::*; 15 | 16 | #[derive(Debug, Clone)] 17 | pub struct ServerAddrs(pub Vec<(SocketAddr, SocketAddr)>); 18 | 19 | impl FromStr for ServerAddrs { 20 | type Err = std::string::ParseError; 21 | fn from_str(s: &str) -> Result { 22 | println!("{}", s); 23 | Ok(ServerAddrs( 24 | s.split('^').map(|t|{ 25 | let mut addrs = t.split('#').map(|s| { 26 | match SocketAddr::from_str(s) { 27 | Ok(addr) => addr, 28 | Err(e) => panic!("head parse err {} @ {}", e, s), 29 | } 30 | }); 31 | let head = addrs.next().expect("no head"); 32 | let tail = if let Some(addr) = addrs.next() { 33 | addr 34 | } else { 35 | head 36 | }; 37 | assert!(addrs.next().is_none()); 38 | (head, tail) 39 | }).collect() 40 | )) 41 | } 42 | } 43 | 44 | impl From> for ServerAddrs { 45 | fn from(v: Vec<(SocketAddr, SocketAddr)>) -> Self { 46 | ServerAddrs(v) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /examples/zookeeper/view2/src/main.rs: -------------------------------------------------------------------------------- 1 | 2 | extern crate mio; 3 | extern crate reactor; 4 | extern crate rand; 5 | extern crate structopt; 6 | pub extern crate serde; 7 | extern crate zk_view as msg; 8 | pub extern crate zookeeper; 9 | 10 | #[macro_use] extern crate structopt_derive; 11 | 12 | use std::sync::Arc; 13 | use std::sync::atomic::AtomicUsize; 14 | use std::sync::atomic::Ordering::Relaxed; 15 | use std::thread; 16 | use std::time::Duration; 17 | 18 | use structopt::StructOpt; 19 | 20 | pub use msg::ServerAddrs; 21 | pub use msg::bincode; 22 | 23 | use view::View; 24 | 25 | pub mod view; 26 | pub mod read_gen; 27 | 28 | #[derive(StructOpt, Debug)] 29 | #[structopt(name = "zk_test", about = "")] 30 | struct Args { 31 | #[structopt(help = "FuzzyLog servers to run against.")] 32 | servers: ServerAddrs, 33 | my_port: u16, 34 | client_num: u32, 35 | num_clients: u32, 36 | window: usize, 37 | views: ServerAddrs, 38 | num_threads: usize, 39 | #[structopt(short="o", long="one_chain")] 40 | one_chain: bool, 41 | #[structopt(short="t", long="transactions")] 42 | transactions_one_in: Option, 43 | } 44 | 45 | fn main() { 46 | let args: Args = StructOpt::from_args(); 47 | 48 | zookeeper::message::set_client_id(args.client_num + 1); 49 | if args.client_num < args.num_clients { 50 | run_view(args) 51 | } else { 52 | run_reads(args) 53 | } 54 | } 55 | 56 | fn run_view(args: Args) { 57 | let completed_writes = Arc::new(AtomicUsize::new(0)); 58 | let cw = completed_writes.clone(); 59 | let client_num = args.client_num; 60 | let num_servers = args.servers.0.len() as u32; 61 | thread::spawn(move || { 62 | let client_num = args.client_num; 63 | let color = if args.one_chain { 64 | (client_num % num_servers + 1).into() 65 | } else { 66 | (client_num + 1).into() 67 | }; 68 | 69 | let roots = if args.one_chain { 70 | (0..args.num_clients) 71 | .map(|i| (format!("foo{}",i).into(), (i % num_servers + 1).into())) 72 | .collect() 73 | } else { 74 | (0..args.num_clients) 75 | .map(|i| (format!("foo{}",i).into(), (i + 1).into())) 76 | .collect() 77 | }; 78 | 79 | let balance_num = if args.one_chain { 80 | [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14] 81 | } else { 82 | [1, 8, 2, 9, 3, 10, 4, 11, 5, 12, 6, 13, 7, 14] 83 | }[client_num as usize]; 84 | 85 | let my_dir = client_num; 86 | let my_root = format!("/foo{}/", my_dir); 87 | 88 | let view = View::new( 89 | args.client_num as usize, 90 | args.num_clients as usize, 91 | args.transactions_one_in, 92 | args.window, 93 | args.my_port, 94 | args.servers, 95 | color, 96 | balance_num, 97 | my_root, 98 | roots, 99 | cw, 100 | ).expect("cannot start view"); 101 | view.run(); 102 | }); 103 | 104 | thread::sleep(Duration::from_secs(2)); 105 | 106 | completed_writes.swap(0, Relaxed); 107 | let mut completed = [0; 10]; 108 | for i in 0..10 { 109 | thread::sleep(Duration::from_secs(1)); 110 | completed[i] = completed_writes.swap(0, Relaxed); 111 | } 112 | thread::sleep(Duration::from_secs(2)); 113 | 114 | let total: usize = completed.iter().sum(); 115 | let avg = total / completed.len(); 116 | 117 | println!("> w {}: {:6} Hz\n", client_num, avg); 118 | println!("w {}: complete {:?}", client_num, completed); 119 | } 120 | 121 | fn run_reads(args: Args) { 122 | return; 123 | let num_threads = args.num_threads; 124 | 125 | let view_addr = args.views.0[(args.client_num % args.num_clients) as usize].0; 126 | let window = args.window / 2; 127 | 128 | let mut ops_completed = vec![[0; 10]; num_threads]; 129 | let completed_reads: Vec<_> = (0..num_threads) 130 | .map(|_| Arc::new(AtomicUsize::new(0))) 131 | .collect(); 132 | 133 | for i in 0..args.num_threads { 134 | let read = completed_reads[i].clone(); 135 | thread::spawn(move || read_gen::work(view_addr, window, read)); 136 | } 137 | 138 | thread::sleep(Duration::from_secs(1)); 139 | 140 | for i in 0..10 { 141 | thread::sleep(Duration::from_secs(1)); 142 | for j in 0..num_threads { 143 | ops_completed[j][i] = completed_reads[j].swap(0, Relaxed); 144 | } 145 | } 146 | 147 | thread::sleep(Duration::from_secs(1)); 148 | for j in 0..num_threads { 149 | println!("r {:2>}.{:}: {:?}", args.client_num, j, ops_completed[j]); 150 | let total_ops: usize = ops_completed[j].iter().sum(); 151 | let ops_s = total_ops / ops_completed[0].len(); 152 | println!("> r {:2>}.{:}: {:?} Hz", args.client_num, j, ops_s); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /examples/zookeeper/view2/src/msg.rs: -------------------------------------------------------------------------------- 1 | 2 | use std::borrow::Cow; 3 | 4 | use zookeeper::{CreateMode, Version, Stat}; 5 | 6 | pub type Id = u64; 7 | 8 | #[derive(Debug, Serialize, Deserialize)] 9 | pub enum Request<'s> { 10 | Create { 11 | id: Id, 12 | path: Cow<'s, str>, 13 | data: Vec, 14 | create_mode: CreateMode, 15 | }, 16 | 17 | Delete { 18 | id: Id, 19 | path: Cow<'s, str>, 20 | version: Version, 21 | }, 22 | 23 | SetData { 24 | id: Id, 25 | path: Cow<'s, str>, 26 | data: Vec, 27 | version: Version, 28 | }, 29 | 30 | // Rename { 31 | // oldPath: Cow<'s, str>, 32 | // newPath: Cow<'s, str>, 33 | // }, 34 | 35 | Exists(Id, Cow<'s, str>), 36 | GetData(Id, Cow<'s, str>), 37 | GetChildren(Id, Cow<'s, str>), 38 | Done, 39 | } 40 | 41 | #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] 42 | pub enum Response { 43 | Ok(Id, String, Vec, Stat, Vec), 44 | Err, 45 | } 46 | -------------------------------------------------------------------------------- /examples/zookeeper/view2/src/read_gen.rs: -------------------------------------------------------------------------------- 1 | use std::net::SocketAddr; 2 | use std::sync::Arc; 3 | use std::sync::atomic::AtomicUsize; 4 | use std::sync::atomic::Ordering::Relaxed; 5 | use std::thread; 6 | use std::time::Duration; 7 | 8 | use ::{bincode, mio, msg}; 9 | 10 | use bincode::Infinite; 11 | 12 | use reactor::*; 13 | 14 | pub fn work(addr: SocketAddr, window: usize, read: Arc) { 15 | use std::io::ErrorKind; 16 | 17 | thread::sleep(Duration::from_secs(1)); 18 | 19 | // let mut stream = mio::net::TcpStream::connect(&addr); 20 | // let stream = loop { 21 | // let reconnect = match stream { 22 | // Ok(s) => break s, 23 | // Err(ref e) if e.kind() != ErrorKind::WouldBlock => 24 | // true, 25 | // Err(..) => {thread::yield_now(); false}, 26 | // }; 27 | // if reconnect { 28 | // stream = mio::net::TcpStream::connect(&addr) 29 | // } 30 | 31 | // }; 32 | 33 | let stream = mio::net::TcpStream::connect(&addr).expect("work gen cannot connect"); 34 | let window = window as u64; 35 | 36 | let mut handler = TcpHandler::new( 37 | stream, 38 | ResponseReader, 39 | ResponseHandler(vec![], window, read) 40 | ); 41 | for i in 0..window { 42 | let op = msg::Request::GetData(i, "/".into()); 43 | let bytes = bincode::serialize(&op, Infinite).unwrap(); 44 | handler.add_writes(&[&*bytes]) 45 | } 46 | let mut generator = Generator::with_inner(1.into(), ()).expect("cannot start gen"); 47 | generator.add_stream(2.into(), handler); 48 | generator.run().expect("cannot run gen"); 49 | } 50 | 51 | /////////////////////////////////////// 52 | 53 | type Generator = Reactor; 54 | type PerStream = TcpHandler; 55 | 56 | /////////////////// 57 | 58 | struct ResponseHandler(Vec, u64, Arc); 59 | 60 | impl MessageHandler<(), msg::Response> for ResponseHandler { 61 | fn handle_message(&mut self, io: &mut TcpWriter, _: &mut (), _message: msg::Response) 62 | -> Result<(), ()> { 63 | self.2.fetch_add(1, Relaxed); 64 | 65 | let i = self.1; 66 | self.1 += 1; 67 | let op = msg::Request::GetData(i, "/".into()); 68 | 69 | self.0.clear(); 70 | bincode::serialize_into(&mut self.0, &op, Infinite).unwrap(); 71 | io.add_bytes_to_write(&[&*self.0]); 72 | Ok(()) 73 | } 74 | } 75 | 76 | /////////////////// 77 | 78 | struct ResponseReader; 79 | 80 | impl MessageReader for ResponseReader { 81 | type Message = msg::Response; 82 | type Error = Box<::bincode::ErrorKind>; 83 | 84 | fn deserialize_message( 85 | &mut self, 86 | bytes: &[u8] 87 | ) -> Result<(Self::Message, usize), MessageReaderError> { 88 | use ::std::io::Cursor; 89 | 90 | let mut cursor = Cursor::new(bytes); 91 | let limit = ::bincode::Bounded(bytes.len() as u64); 92 | let res = ::bincode::deserialize_from(&mut cursor, limit); 93 | match res { 94 | Ok(val) => Ok((val, cursor.position() as usize)), 95 | Err(error) => { 96 | if let &::bincode::ErrorKind::SizeLimit = &*error { 97 | return Err(MessageReaderError::NeedMoreBytes(1)) 98 | } 99 | Err(MessageReaderError::Other(error)) 100 | }, 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /fuzzy_log_client/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fuzzy_log_client" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | fuzzy_log_packets = {path = "../fuzzy_log_packets"} 8 | fuzzy_log_util = {path = "../fuzzy_log_util"} 9 | log = "0.3" 10 | mio = "0.6.6" 11 | reactor = {path = "../reactor"} 12 | 13 | [features] 14 | print_stats = [] 15 | -------------------------------------------------------------------------------- /fuzzy_log_client/src/colors.rs: -------------------------------------------------------------------------------- 1 | //TODO store sender in lazy tls for thread safety 2 | //fn append requires append and wait-for-append 3 | //fn snapshot requires snapshot(chain[s]) + start-prefetch(chain) 4 | //fn get-next 5 | -------------------------------------------------------------------------------- /fuzzy_log_client/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(deprecated)] //TODO we're using an old mio, need to move queues in tree and update 2 | 3 | pub extern crate fuzzy_log_packets as packets; 4 | #[macro_use] extern crate fuzzy_log_util; 5 | 6 | #[macro_use] extern crate log; 7 | pub extern crate mio; 8 | extern crate reactor; 9 | 10 | pub use fuzzy_log_util::hash; 11 | 12 | pub use fuzzy_log::log_handle::*; 13 | 14 | pub mod fuzzy_log; 15 | pub mod colors; 16 | pub mod store; 17 | pub mod replicator; 18 | -------------------------------------------------------------------------------- /fuzzy_log_packets/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fuzzy_log_packets" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | bitflags = "0.4" 8 | custom_derive = "0.1" 9 | newtype_derive = "0.1" 10 | packet-macro2 = {path = "../packet-macro2"} 11 | packet-macro-impl = {path = "../packet-macro2/packet-macro-impl"} 12 | uuid = { version = "0.4", features = ["v4"] } 13 | rustc-serialize = "0.3" 14 | 15 | [dev-dependencies] 16 | byteorder = "1" 17 | -------------------------------------------------------------------------------- /fuzzy_log_server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fuzzy_log_server" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | byteorder = "1" 8 | deque = "0.3.1" 9 | evmap = "0.6.4" 10 | fuzzy_log_packets = {path = "../fuzzy_log_packets"} 11 | fuzzy_log_util = {path = "../fuzzy_log_util"} 12 | lazycell = "0.5.0" 13 | log = "0.3" 14 | mio = "0.6.6" 15 | uuid = { version = "0.4", features = ["v4"] } 16 | reactor = {path = "../reactor"} 17 | 18 | [dev-dependencies] 19 | env_logger = "0.3" 20 | 21 | [features] 22 | no_trace = ["log/max_level_info"] 23 | print_stats = [] 24 | -------------------------------------------------------------------------------- /fuzzy_log_server/src/spmc.rs: -------------------------------------------------------------------------------- 1 | use std::io; 2 | use std::sync::Arc; 3 | use std::sync::mpsc; 4 | 5 | use deque::{self, Stolen, Worker, Stealer}; 6 | 7 | use mio::{self, Evented, Poll, PollOpt, Registration, SetReadiness, Token}; 8 | 9 | use lazycell::{LazyCell, AtomicLazyCell}; 10 | 11 | // XXX XXX THIS DOES NOT WORK 12 | 13 | // based heavily on mio::channel 14 | 15 | pub fn channel() -> (Sender, Receiver) { 16 | let (worker, stealer) = deque::new(); 17 | let (send, recv) = mpsc::channel(); 18 | let sender = Sender { inner: worker, sleepers: recv }; 19 | let reciever = Receiver { 20 | inner: stealer, 21 | registration: LazyCell::new(), 22 | notifier: Arc::new(AtomicLazyCell::new()), 23 | sleepers: send 24 | }; 25 | (sender, reciever) 26 | } 27 | 28 | pub struct Sender { 29 | inner: Worker, 30 | sleepers: mpsc::Receiver>, 31 | } 32 | 33 | pub struct Receiver { 34 | inner: Stealer, 35 | registration: LazyCell, 36 | notifier: Arc, 37 | sleepers: mpsc::Sender>, 38 | } 39 | 40 | type Notifier = AtomicLazyCell; 41 | 42 | impl Sender 43 | where V: Send { 44 | pub fn send(&self, v: V) { 45 | self.inner.push(v); 46 | if let Ok(note) = self.sleepers.try_recv() { 47 | if let Some(set_readiness) = note.borrow() { 48 | set_readiness.set_readiness(mio::Ready::readable()).unwrap(); 49 | } 50 | } 51 | } 52 | } 53 | 54 | impl Receiver 55 | where V: Send { 56 | pub fn steal(&self) -> Stolen { 57 | self.inner.steal() 58 | } 59 | 60 | pub fn steal_or_set_unready(&self) -> Stolen { 61 | match self.inner.steal() { 62 | s @ Stolen::Abort | s @ Stolen::Data(..) => return s, 63 | s @ Stolen::Empty => { 64 | if let Some(notifier) = self.notifier.borrow() { 65 | //FIXME is this right? 66 | if notifier.readiness().is_readable() { 67 | notifier.set_readiness(mio::Ready::none()).unwrap(); 68 | let _ = self.sleepers.send(self.notifier.clone()); 69 | } 70 | } 71 | return s 72 | }, 73 | } 74 | } 75 | 76 | pub fn try_recv(&self) -> Option { 77 | loop { 78 | match self.steal_or_set_unready() { 79 | Stolen::Empty => return None, 80 | Stolen::Data(v) => return Some(v), 81 | Stolen::Abort => continue, 82 | } 83 | } 84 | } 85 | } 86 | 87 | impl Clone for Receiver { 88 | fn clone(&self) -> Self { 89 | Receiver { 90 | inner: self.inner.clone(), 91 | registration: LazyCell::new(), 92 | notifier: Arc::new(AtomicLazyCell::new()), 93 | sleepers: self.sleepers.clone(), 94 | } 95 | } 96 | } 97 | 98 | impl Evented for Receiver { 99 | fn register(&self, poll: &Poll, token: Token, interest: mio::Ready, opts: PollOpt) -> io::Result<()> { 100 | if self.registration.borrow().is_some() { 101 | return Err(io::Error::new(io::ErrorKind::Other, "receiver already registered")); 102 | } 103 | 104 | let (registration, set_readiness) = Registration::new(poll, token, interest, opts); 105 | 106 | let _ = set_readiness.set_readiness(mio::Ready::readable()); 107 | 108 | self.registration.fill(registration).ok().expect("unexpected state encountered"); 109 | self.notifier.fill(set_readiness).ok().expect("unexpected state encountered"); 110 | 111 | Ok(()) 112 | } 113 | 114 | fn reregister(&self, poll: &Poll, token: Token, interest: mio::Ready, opts: PollOpt) -> io::Result<()> { 115 | match self.registration.borrow() { 116 | Some(registration) => registration.update(poll, token, interest, opts), 117 | None => Err(io::Error::new(io::ErrorKind::Other, "receiver not registered")), 118 | } 119 | } 120 | 121 | fn deregister(&self, poll: &Poll) -> io::Result<()> { 122 | match self.registration.borrow() { 123 | Some(registration) => registration.deregister(poll), 124 | None => Err(io::Error::new(io::ErrorKind::Other, "receiver not registered")), 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /fuzzy_log_server/src/tcp/buffer_stream.rs: -------------------------------------------------------------------------------- 1 | use std::cell::RefCell; 2 | use std::collections::{LinkedList, VecDeque}; 3 | use std::rc::Rc; 4 | 5 | use fuzzy_log_packets::Packet; 6 | 7 | #[derive(Default, Clone)] 8 | pub struct BufferStream { 9 | inner: Rc>, 10 | } 11 | 12 | #[derive(Default)] 13 | struct Inner { 14 | stream: LinkedList>, 15 | returned: VecDeque>, 16 | } 17 | 18 | const MAX_BUFFER_SIZE: usize = 8 * 1024; 19 | 20 | impl BufferStream { 21 | pub fn add_buffer(&self, buffer: Vec) { 22 | let mut inner = self.inner.borrow_mut(); 23 | let added = inner.try_append_bytes(&buffer); 24 | if !added { 25 | inner.append_buffer(buffer); 26 | } 27 | if let Some(task) = inner.blocked.take() { 28 | task.notify(); 29 | } 30 | } 31 | 32 | pub fn add_slice(&self, bytes: &[u8]) { 33 | let mut inner = self.inner.borrow_mut(); 34 | let added = inner.try_append_bytes(bytes); 35 | if !added { 36 | let buffer = inner.into_vec(bytes); 37 | inner.append_buffer(buffer); 38 | } 39 | if let Some(task) = inner.blocked.take() { 40 | task.notify(); 41 | } 42 | } 43 | 44 | pub fn add_contents(&mut self, contents: Packet::Ref) { 45 | let mut inner = self.inner.borrow_mut(); 46 | inner.add_contents(contents); 47 | if let Some(task) = inner.blocked.take() { 48 | task.notify(); 49 | } 50 | } 51 | 52 | pub fn return_buffer(&self, buffer: Vec) { 53 | let mut inner = self.inner.borrow_mut(); 54 | inner.return_buffer(buffer) 55 | } 56 | } 57 | 58 | impl Inner { 59 | fn try_append_bytes(&mut self, bytes: &[u8]) -> bool { 60 | match self.stream.back_mut() { 61 | None => return false, 62 | Some(buffer) => { 63 | if buffer.len() + bytes.len() > MAX_BUFFER_SIZE { 64 | return false; 65 | } 66 | buffer.extend_from_slice(bytes); 67 | return true; 68 | } 69 | } 70 | } 71 | 72 | fn append_buffer(&mut self, buffer: Vec) { 73 | self.stream.push_back(buffer) 74 | } 75 | 76 | fn add_contents(&mut self, contents: Packet::Ref) { 77 | let contents_len = contents.len(); 78 | match self.stream.back_mut() { 79 | None => (), 80 | Some(ref mut buffer) => if buffer.len() + contents_len <= MAX_BUFFER_SIZE { 81 | contents.fill_vec(buffer); 82 | return; 83 | }, 84 | }; 85 | let mut buffer = if self.returned.is_empty() { 86 | vec![] 87 | } else if contents_len > self.returned[0].capacity() { 88 | vec![] 89 | } else { 90 | self.returned.pop_front().unwrap() 91 | }; 92 | 93 | contents.fill_vec(&mut buffer); 94 | self.stream.push_back(buffer); 95 | } 96 | 97 | fn into_vec(&mut self, bytes: &[u8]) -> Vec { 98 | if self.returned.is_empty() { 99 | return bytes.to_vec(); 100 | } 101 | 102 | if self.returned.front().unwrap().capacity() < bytes.len() { 103 | return bytes.to_vec(); 104 | } 105 | 106 | let mut buffer = self.returned.pop_front().unwrap(); 107 | 108 | buffer.extend_from_slice(bytes); 109 | buffer 110 | } 111 | 112 | fn return_buffer(&mut self, mut buffer: Vec) { 113 | buffer.clear(); 114 | let buffer = buffer; 115 | if self.returned.is_empty() { 116 | self.returned.push_back(buffer); 117 | return; 118 | } 119 | 120 | if self.returned.len() == 1 { 121 | if self.returned[0].capacity() < buffer.capacity() { 122 | self.returned.push_front(buffer); 123 | } else { 124 | self.returned.push_back(buffer); 125 | } 126 | return; 127 | } 128 | 129 | if self.returned[0].capacity() < buffer.capacity() { 130 | self.returned.pop_back(); 131 | self.returned.push_front(buffer); 132 | return; 133 | } 134 | 135 | if self.returned[1].capacity() < buffer.capacity() { 136 | self.returned.pop_back(); 137 | self.returned.push_back(buffer); 138 | return; 139 | } 140 | ::std::mem::drop(buffer) 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /fuzzy_log_server/src/tcp/per_socket.rs: -------------------------------------------------------------------------------- 1 | // use prelude::*; 2 | 3 | use std::collections::{/*LinkedList,*/ VecDeque}; 4 | use std::io::{self, ErrorKind}; 5 | use std::mem; 6 | use socket_addr::Ipv4SocketAddr; 7 | 8 | use byteorder::{ByteOrder, LittleEndian}; 9 | 10 | use mio::tcp::*; 11 | 12 | use buffer::Buffer; 13 | 14 | use packets::EntryContents; 15 | 16 | use super::*; 17 | 18 | use self::worker::WorkerInner; 19 | 20 | use reactor::*; 21 | 22 | pub type PerStream = TcpHandler; 23 | 24 | #[derive(Debug)] 25 | pub struct WriteHandler { 26 | upstream: Option, 27 | } 28 | 29 | #[derive(Debug)] 30 | pub struct PacketHandler { 31 | token: mio::Token, 32 | } 33 | 34 | pub fn new_stream( 35 | stream: TcpStream, token: mio::Token, is_replica: bool, upstream: Option 36 | ) -> PerStream { 37 | let reader = PacketReader{ 38 | buffer_cache: Default::default(), 39 | is_replica, 40 | }; 41 | let ps = (stream, reader, PacketHandler{ token }, WriteHandler{ upstream }).into(); 42 | let _: &Handler<_, Error=io::Error> = &ps as &Handler<_, Error=io::Error>; 43 | ps 44 | } 45 | 46 | impl MessageHandler)> for PacketHandler { 47 | fn handle_message( 48 | &mut self, 49 | io: &mut TcpWriter, 50 | inner: &mut WorkerInner, 51 | (msg, addr, storage_loc): (Buffer, Ipv4SocketAddr, Option), 52 | ) -> Result<(), ()> { 53 | // trace!("{} {:?}", addr, storage_loc); 54 | inner.handle_message(io, self.token, msg, addr, storage_loc) 55 | } 56 | } 57 | 58 | impl AfterWrite for WriteHandler { 59 | fn after_write( 60 | &mut self, 61 | io: &mut TcpWriter, 62 | inner: &mut WorkerInner, 63 | _token: mio::Token, 64 | _wrote: usize, 65 | ) { 66 | if let (Some(upstream), false) = (self.upstream, io.is_overflowing()) { 67 | inner.end_backpressure(upstream) 68 | } 69 | } 70 | } 71 | 72 | pub trait PerSocket { 73 | fn return_buffer(&mut self, buffer: Buffer); 74 | } 75 | 76 | impl PerSocket for PerStream { 77 | fn return_buffer(&mut self, _buffer: Buffer) {} 78 | } 79 | 80 | pub fn add_contents(io: &mut TcpWriter, contents: EntryContents) { 81 | io.add_contents_to_write(contents, &[]) 82 | } 83 | 84 | pub struct PacketReader { 85 | buffer_cache: VecDeque, 86 | is_replica: bool, 87 | } 88 | 89 | impl MessageReader for PacketReader { 90 | type Message = (Buffer, Ipv4SocketAddr, Option); 91 | type Error = ErrorKind; 92 | 93 | fn deserialize_message( 94 | &mut self, 95 | bytes: &[u8] 96 | ) -> Result<(Self::Message, usize), MessageReaderError> { 97 | use self::MessageReaderError::*; 98 | use packets::Packet::WrapErr; 99 | 100 | let extra = if self.is_replica { mem::size_of::() } else { 0 }; 101 | 102 | let to_read = unsafe { EntryContents::try_ref(bytes).map(|(c, _)| c.len()) }; 103 | let size = to_read.map_err(|e| match e { 104 | WrapErr::NotEnoughBytes(needs) => 105 | NeedMoreBytes(needs + mem::size_of::() + extra), 106 | _ => Other(ErrorKind::InvalidInput), 107 | })?; 108 | 109 | if bytes.len() < size + extra + mem::size_of::() { 110 | let needs = size + extra + mem::size_of::() - bytes.len(); 111 | return Err(NeedMoreBytes(needs))? 112 | } 113 | 114 | 115 | //FIXME buffer cache 116 | let buffer = Buffer::wrap_vec(bytes[..size].to_vec()); 117 | let storage_loc = match self.is_replica { 118 | false => { 119 | assert_eq!(extra, 0); 120 | None 121 | }, 122 | true => { 123 | let end = size + extra; 124 | let storage_loc = LittleEndian::read_u64(&bytes[size..end]); 125 | Some(storage_loc) 126 | }, 127 | }; 128 | let src_addr = Ipv4SocketAddr::from_slice(&bytes[(size + extra)..]); 129 | let size_read = size + extra + mem::size_of::(); 130 | Ok(((buffer, src_addr, storage_loc), size_read)) 131 | } 132 | 133 | } 134 | -------------------------------------------------------------------------------- /fuzzy_log_server/src/trivial_eq_arc.rs: -------------------------------------------------------------------------------- 1 | use std::cell::UnsafeCell; 2 | use std::sync::Arc; 3 | 4 | #[derive(Debug)] 5 | pub struct TrivialEqArc(Arc>); 6 | 7 | impl TrivialEqArc { 8 | pub fn new(t: T) -> Self { 9 | TrivialEqArc(Arc::new(UnsafeCell::new(t))) 10 | } 11 | 12 | pub fn get(this: &Self) -> &T { 13 | unsafe { &*this.0.get() } 14 | } 15 | } 16 | 17 | impl ::std::ops::Deref for TrivialEqArc { 18 | type Target = Arc>; 19 | fn deref(&self) -> &Self::Target { 20 | &self.0 21 | } 22 | } 23 | 24 | impl ::std::ops::DerefMut for TrivialEqArc { 25 | fn deref_mut(&mut self) -> &mut Self::Target { 26 | &mut self.0 27 | } 28 | } 29 | 30 | impl PartialEq for TrivialEqArc { 31 | fn eq(&self, other: &TrivialEqArc) -> bool { 32 | Arc::ptr_eq(self, other) 33 | } 34 | } 35 | 36 | impl Clone for TrivialEqArc { 37 | fn clone(&self) -> Self { 38 | TrivialEqArc(Arc::clone(&self.0)) 39 | } 40 | } 41 | 42 | impl Eq for TrivialEqArc {} 43 | unsafe impl Send for TrivialEqArc {} 44 | -------------------------------------------------------------------------------- /fuzzy_log_util/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fuzzy_log_util" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | byteorder = "1" 8 | uuid = { version = "0.4", features = ["v4"] } 9 | -------------------------------------------------------------------------------- /fuzzy_log_util/src/counter_macro.rs: -------------------------------------------------------------------------------- 1 | #[macro_export] 2 | macro_rules! counters { 3 | (struct $name:ident { $($field:ident: $typ:tt),* $(,)* }) => { 4 | #[allow(dead_code)] 5 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Default)] 6 | pub struct $name { 7 | $(#[cfg(feature = "print_stats")] $field: $typ),* 8 | } 9 | 10 | #[allow(dead_code)] 11 | impl $name { 12 | $( 13 | #[inline(always)] 14 | fn $field(&mut self, _increment: $typ) { 15 | #[cfg(feature = "print_stats")] 16 | { 17 | self.$field += _increment 18 | } 19 | } 20 | )* 21 | } 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /fuzzy_log_util/src/lib.rs: -------------------------------------------------------------------------------- 1 | 2 | extern crate byteorder; 3 | pub extern crate uuid; 4 | 5 | pub use hash_deque_map as vec_deque_map; 6 | 7 | pub mod counter_macro; 8 | pub mod hash; 9 | pub mod socket_addr; 10 | pub mod range_tree; 11 | //pub mod vec_deque_map; 12 | 13 | pub mod tree_deque_map; 14 | pub mod hash_deque_map; 15 | -------------------------------------------------------------------------------- /fuzzy_log_util/src/socket_addr.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | 3 | use uuid::Uuid; 4 | 5 | #[derive(Copy, Clone, PartialEq, Eq, Hash)] 6 | #[repr(C)] 7 | pub struct Ipv4SocketAddr { 8 | bytes: [u8; 16], 9 | } 10 | 11 | impl Ipv4SocketAddr { 12 | 13 | pub fn random() -> Self { 14 | Self::from_uuid(&Uuid::new_v4()) 15 | } 16 | 17 | pub fn from_bytes(bytes: [u8; 16]) -> Self { 18 | Ipv4SocketAddr { bytes: bytes } 19 | } 20 | 21 | pub fn from_u64(num: u64) -> Self { 22 | use ::byteorder::{LittleEndian, ByteOrder}; 23 | let mut bytes = [0; 16]; 24 | LittleEndian::write_u64(&mut bytes, num); 25 | Ipv4SocketAddr { bytes: bytes } 26 | } 27 | 28 | pub fn from_slice(slice: &[u8]) -> Self { 29 | let slice = &slice[..16]; 30 | let mut bytes = [0; 16]; 31 | bytes.copy_from_slice(slice); 32 | Ipv4SocketAddr { bytes: bytes } 33 | } 34 | 35 | pub fn from_uuid(id: &Uuid) -> Self { 36 | Self::from_bytes(*id.as_bytes()) 37 | } 38 | 39 | pub fn nil() -> Self { 40 | Ipv4SocketAddr { bytes: [0; 16] } 41 | } 42 | 43 | pub fn bytes(&self) -> &[u8; 16] { 44 | &self.bytes 45 | } 46 | 47 | pub fn to_uuid(&self) -> Uuid { 48 | Uuid::from_bytes(&self.bytes).unwrap() 49 | } 50 | } 51 | 52 | impl From for Ipv4SocketAddr { 53 | fn from(id: Uuid) -> Self { 54 | Self::from_uuid(&id) 55 | } 56 | } 57 | 58 | impl From for Ipv4SocketAddr { 59 | fn from(id: u64) -> Self { 60 | Self::from_u64(id) 61 | } 62 | } 63 | 64 | impl fmt::Debug for Ipv4SocketAddr { 65 | fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { 66 | Ok(try!(fmt.write_fmt(format_args!("{:?}", Uuid::from_bytes(&*self.bytes()))))) 67 | } 68 | } 69 | 70 | impl fmt::Display for Ipv4SocketAddr { 71 | fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { 72 | Ok(try!(fmt.write_fmt(format_args!("{}", &Uuid::from_bytes(&*self.bytes()).unwrap())))) 73 | } 74 | } 75 | 76 | #[cfg(test)] 77 | mod tests { 78 | use super::*; 79 | 80 | use std::mem; 81 | 82 | #[test] 83 | fn test_size() { 84 | assert_eq!(mem::size_of::(), 16); 85 | } 86 | 87 | #[test] 88 | fn test_align() { 89 | assert_eq!(mem::align_of::(), 1); 90 | } 91 | 92 | #[test] 93 | fn test_from_u64_id_hash() { 94 | use std::hash::{Hash, Hasher}; 95 | use hash::{UuidHasher, IdHasher}; 96 | for i in 0..100 { 97 | let mut hasher = IdHasher::default(); 98 | let addr = Ipv4SocketAddr::from_u64(i); 99 | addr.hash(&mut hasher); 100 | assert_eq!(hasher.finish(), i); 101 | } 102 | 103 | for i in 0..100 { 104 | let mut hasher = UuidHasher::default(); 105 | let addr = Ipv4SocketAddr::from_u64(i); 106 | addr.hash(&mut hasher); 107 | assert_eq!(hasher.finish(), i); 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /fuzzy_views/bloom/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bloom" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | crossbeam = "0.2.10" 8 | env_logger = "0.3" 9 | fuzzy_log = {path = "../.."} 10 | log = "0.3" 11 | mio = "0.6.6" 12 | rand = "0.3" 13 | structopt = "0.0.5" 14 | structopt-derive = "0.0.5" 15 | zipf = "1.0.0" 16 | -------------------------------------------------------------------------------- /fuzzy_views/color_alloc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "color_alloc" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | bincode = "0.8.0" 8 | fuzzy_log_util = {path = "../../fuzzy_log_util"} 9 | fuzzy_log_client = {path = "../../fuzzy_log_client"} 10 | serde = "1" 11 | serde_derive = "1" 12 | 13 | [dev-dependencies] 14 | fuzzy_log_server = {path = "../../fuzzy_log_server"} 15 | -------------------------------------------------------------------------------- /fuzzy_views/color_alloc/src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate bincode; 2 | extern crate fuzzy_log_util; 3 | extern crate fuzzy_log_client; 4 | pub extern crate serde; 5 | #[macro_use] extern crate serde_derive; 6 | 7 | #[cfg(test)] extern crate fuzzy_log_server; 8 | 9 | use std::collections::HashMap; 10 | 11 | use bincode::{serialize, deserialize, Infinite}; 12 | 13 | use fuzzy_log_util::range_tree::RangeTree; 14 | 15 | pub use fuzzy_log_client::fuzzy_log::log_handle::{ 16 | order, 17 | OrderIndex, 18 | GetRes, 19 | LogHandle, 20 | }; 21 | 22 | pub type Handle = LogHandle<[u8]>; 23 | 24 | #[derive(Debug, Serialize, Deserialize)] 25 | struct Allocation<'a> { 26 | num_colors: u64, 27 | key: &'a [u8], 28 | } 29 | 30 | pub struct Allocator { 31 | used_keys: HashMap, (u64, u64)>, 32 | allocated: RangeTree, 33 | alloc_color: order, 34 | } 35 | 36 | impl Allocator { 37 | pub fn new() -> Self { 38 | Self::with_allocator_color(order::from(1)) 39 | } 40 | 41 | fn with_allocator_color(alloc_color: order) -> Self { 42 | Allocator { 43 | alloc_color, 44 | allocated: RangeTree::with_default_val(false), 45 | used_keys: Default::default(), 46 | } 47 | } 48 | 49 | pub fn allocate(&mut self, handle: &mut Handle, num_colors: u64, key: &[u8]) -> Vec { 50 | let data = serialize(&Allocation{ num_colors, key }, Infinite).unwrap(); 51 | handle.append(self.alloc_color, &data[..], &[]); 52 | self.update_allocations(handle).get_allocation_for(key).unwrap() 53 | } 54 | 55 | pub fn update_allocations(&mut self, handle: &mut Handle) -> &mut Self { 56 | handle.snapshot(self.alloc_color); 57 | loop { 58 | match handle.get_next() { 59 | Err(GetRes::Done) => return self, 60 | Err(e) => panic!("{:?}", e), 61 | Ok((bytes, _)) => { 62 | let Allocation {key, num_colors} = deserialize(bytes).unwrap(); 63 | let alloc_start = self.allocated.iter() 64 | .filter_map(|(range, &alloc)| if alloc { 65 | Some(range.last() + 1) 66 | } else { 67 | None 68 | }) 69 | .next() 70 | .unwrap_or(2); 71 | if self.used_keys.get(key).is_some() { 72 | continue 73 | } 74 | 75 | self.used_keys.insert(key.to_vec(), (alloc_start, num_colors)); 76 | self.allocated.set_range_as(alloc_start, alloc_start+num_colors-1, true); 77 | }, 78 | } 79 | } 80 | } 81 | 82 | pub fn get_allocation_for(&self, key: &[u8]) -> Option> { 83 | self.used_keys.get(key).map(|&(start, end)| 84 | (start..end).map(|i| order::from(i as u32)).collect() 85 | ) 86 | } 87 | } 88 | 89 | pub fn allocate(handle: &mut Handle, num_colors: u64, key: &[u8]) -> Vec { 90 | let mut alloc = Allocator::new(); 91 | handle.rewind(OrderIndex(alloc.alloc_color, 0.into())); 92 | alloc.allocate(handle, num_colors, key) 93 | } 94 | 95 | pub fn get_allocation_for(handle: &mut Handle, key: &[u8]) -> Option> { 96 | let mut alloc = Allocator::new(); 97 | handle.rewind(OrderIndex(alloc.alloc_color, 0.into())); 98 | alloc.update_allocations(handle).get_allocation_for(key) 99 | } 100 | 101 | #[cfg(test)] 102 | mod tests { 103 | #[test] 104 | fn it_works() { 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /fuzzy_views/counter/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "counter" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | crossbeam = "0.2.10" 8 | env_logger = "0.3" 9 | fuzzy_log = {path = "../.."} 10 | log = "0.3" 11 | mio = "0.6.6" 12 | rand = "0.3" 13 | structopt = "0.0.5" 14 | structopt-derive = "0.0.5" 15 | -------------------------------------------------------------------------------- /fuzzy_views/counter2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "counter" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | crossbeam = "0.2.10" 8 | env_logger = "0.3" 9 | fuzzy_log_client = {path = "../../fuzzy_log_client"} 10 | log = "0.3" 11 | mio = "0.6.6" 12 | rand = "0.3" 13 | structopt = "0.0.5" 14 | structopt-derive = "0.0.5" 15 | -------------------------------------------------------------------------------- /fuzzy_views/counter_err/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "counter" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | crossbeam = "0.2.10" 8 | env_logger = "0.3" 9 | fuzzy_log_client = {path = "../../fuzzy_log_client"} 10 | log = "0.3" 11 | mio = "0.6.6" 12 | rand = "0.3" 13 | structopt = "0.0.5" 14 | structopt-derive = "0.0.5" 15 | -------------------------------------------------------------------------------- /fuzzy_views/lat_v_num_events/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "lat_v_even" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | crossbeam = "0.2.10" 8 | env_logger = "0.3" 9 | fuzzy_log = {path = "../.."} 10 | log = "0.3" 11 | mio = "0.6.6" 12 | structopt = "0.0.5" 13 | structopt-derive = "0.0.5" 14 | -------------------------------------------------------------------------------- /fuzzy_views/lat_v_num_events/src/main.rs: -------------------------------------------------------------------------------- 1 | 2 | extern crate crossbeam; 3 | extern crate env_logger; 4 | extern crate fuzzy_log; 5 | 6 | extern crate structopt; 7 | #[macro_use] 8 | extern crate structopt_derive; 9 | 10 | use std::iter; 11 | use std::net::SocketAddr; 12 | use std::time::{Duration, Instant}; 13 | 14 | use fuzzy_log::async::fuzzy_log::log_handle::{LogHandle, GetRes}; 15 | use fuzzy_log::packets::{order, OrderIndex}; 16 | 17 | use structopt::StructOpt; 18 | 19 | #[derive(StructOpt, Debug)] 20 | #[structopt(name = "lat_v_event", about = "latency vs num events benchmark.")] 21 | struct Args { 22 | #[structopt(help = "head of the FuzzyLog server chain to run against.")] 23 | head_server: SocketAddr, 24 | 25 | #[structopt(help = "tail of the FuzzyLog server chain to run against.")] 26 | tail_server: Option, 27 | 28 | #[structopt(short="r", long="rounds", help = "number of rounds.", default_value = "10000")] 29 | num_rounds: usize, 30 | } 31 | 32 | fn main() { 33 | let start_time = Instant::now(); 34 | let _ = env_logger::init(); 35 | let args @ Args{..} = StructOpt::from_args(); 36 | println!("#{:?}", args); 37 | let mut avg_latencies = Vec::new(); 38 | let num_events = [1, 10, 20, 40, 80, 160, 320, 640, 1280]; 39 | 40 | for &events in num_events.into_iter() { 41 | let (l, w) = get_latency(&mut avg_latencies, &args, events); 42 | println!("{:?}events: {:>5}ns\t {:.1}", 43 | events, l, w); 44 | } 45 | 46 | println!("#elapsed {:?}", start_time.elapsed()); 47 | println!("events = {:?}", num_events); 48 | println!("{:?}", avg_latencies); 49 | } 50 | 51 | ///////////////////////// 52 | 53 | #[inline(never)] 54 | fn get_latency( 55 | avg_latencies: &mut Vec, args: &Args, events: usize) -> (u32, u64) { 56 | let chain = order::from(events as u32); 57 | let mut log = if let Some(tail_server) = args.tail_server { 58 | LogHandle::replicated_with_servers( 59 | iter::once((args.head_server, tail_server))) 60 | .chains(iter::once(chain)) 61 | .build() 62 | } else { 63 | LogHandle::unreplicated_with_servers(iter::once(args.head_server)) 64 | .chains(iter::once(chain)) 65 | .build() 66 | }; 67 | 68 | let bytes = vec![0xf; 40]; 69 | 70 | let write_start = Instant::now(); 71 | for _ in 0..events { 72 | log.async_append(chain, &bytes[..], &[]); 73 | } 74 | log.wait_for_all_appends().unwrap(); 75 | let write_time = write_start.elapsed(); 76 | println!("writes took {}.{:010}s", write_time.as_secs(), write_time.subsec_nanos()); 77 | 78 | let mut latencies = Vec::with_capacity(args.num_rounds); 79 | 80 | let mut work = 0u64; 81 | let lat; 82 | 83 | { 84 | let mut record_latency = |chain| { 85 | for _ in 0..args.num_rounds { 86 | let mut num_events = 0; 87 | let start_time = Instant::now(); 88 | log.snapshot(chain); 89 | 'recv1: loop { 90 | let next = log.get_next(); 91 | match next { 92 | Ok((b, _)) =>{ 93 | work = work.wrapping_add(b.iter().fold(0, 94 | |a, &b| a.wrapping_add(b as u64))); 95 | num_events += 1; 96 | }, 97 | Err(GetRes::Done) => break 'recv1, 98 | Err(r) => panic!("{:?}", r), 99 | } 100 | } 101 | let lat = start_time.elapsed(); 102 | assert_eq!(num_events, events); 103 | latencies.push(lat); 104 | log.rewind(OrderIndex(chain.into(), 1.into())) 105 | } 106 | 107 | let sum: Duration = latencies.drain(..).sum(); 108 | let avg: Duration = sum / (args.num_rounds as u32); 109 | assert_eq!(avg.as_secs(), 0); 110 | avg.subsec_nanos() 111 | }; 112 | 113 | lat = record_latency(chain); 114 | } 115 | 116 | avg_latencies.push(lat); 117 | 118 | (lat, work) 119 | } 120 | -------------------------------------------------------------------------------- /fuzzy_views/micropayments/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "micropayments_bench" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | crossbeam = "0.2.10" 8 | env_logger = "0.3" 9 | fuzzy_log = {path = "../.."} 10 | log = "0.3" 11 | mio = "0.6.6" 12 | rand = "0.3" 13 | structopt = "0.0.5" 14 | structopt-derive = "0.0.5" 15 | 16 | [profile.release] 17 | opt-level = 3 18 | debug = true 19 | rpath = false 20 | #lto = true 21 | lto = false 22 | debug-assertions = false 23 | codegen-units = 1 24 | panic = 'abort' 25 | 26 | [features] 27 | #default = ["fuzzy_log/no_trace", "log/max_level_info"] 28 | -------------------------------------------------------------------------------- /fuzzy_views/ml/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ml" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | aho-corasick = "0.6.3" 8 | crossbeam = "0.2.10" 9 | env_logger = "0.3" 10 | fuzzy_log = {path = "../.."} 11 | memmap = "0.5.2" 12 | mio = "0.6.6" 13 | rand = "0.3" 14 | structopt = "0.0.5" 15 | structopt-derive = "0.0.5" 16 | 17 | [profile.dev] 18 | panic = "abort" 19 | 20 | [profile.release] 21 | panic = "abort" 22 | -------------------------------------------------------------------------------- /fuzzy_views/pre_v_post/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pre_v_post" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | crossbeam = "0.2.10" 8 | env_logger = "0.3" 9 | fuzzy_log = {path = "../.."} 10 | log = "0.3" 11 | mio = "0.6.6" 12 | rand = "0.3" 13 | structopt = "0.0.5" 14 | structopt-derive = "0.0.5" 15 | -------------------------------------------------------------------------------- /fuzzy_views/pre_v_post_s/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pre_v_post" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | crossbeam = "0.2.10" 8 | env_logger = "0.3" 9 | fuzzy_log = {path = "../.."} 10 | log = "0.3" 11 | mio = "0.6.6" 12 | rand = "0.3" 13 | structopt = "0.0.5" 14 | structopt-derive = "0.0.5" 15 | -------------------------------------------------------------------------------- /fuzzy_views/pre_v_post_s/src/main.rs: -------------------------------------------------------------------------------- 1 | 2 | extern crate crossbeam; 3 | extern crate env_logger; 4 | extern crate fuzzy_log; 5 | extern crate rand; 6 | 7 | extern crate structopt; 8 | #[macro_use] 9 | extern crate structopt_derive; 10 | 11 | use std::iter; 12 | use std::net::SocketAddr; 13 | use std::time::{Duration, Instant}; 14 | 15 | use fuzzy_log::async::fuzzy_log::log_handle::{LogHandle, GetRes}; 16 | use fuzzy_log::packets::{order, OrderIndex}; 17 | 18 | use structopt::StructOpt; 19 | 20 | use rand::Rng; 21 | 22 | #[derive(StructOpt, Debug)] 23 | #[structopt(name = "pre_v_post", about = "pre vs post-hoc filtering benchmark.")] 24 | struct Args { 25 | #[structopt(help = "head of the FuzzyLog server chain to run against.")] 26 | head_server: SocketAddr, 27 | 28 | #[structopt(help = "tail of the FuzzyLog server chain to run against.")] 29 | tail_server: Option, 30 | 31 | #[structopt(short="r", long="rounds", help = "number of rounds.", default_value = "10000")] 32 | num_rounds: usize, 33 | } 34 | 35 | fn main() { 36 | let start_time = Instant::now(); 37 | let _ = env_logger::init(); 38 | let args @ Args{..} = StructOpt::from_args(); 39 | println!("#{:?}", args); 40 | 41 | let mut avg_latencies = Vec::new(); 42 | //let byte_sizes = [1, 10, 100, 1_000, 10_000, 100_000, 1_000_000]; 43 | let byte_sizes = [10_000, 100_000, 1_000_000]; 44 | 45 | for &bytes in byte_sizes.into_iter() { 46 | let ((b, f, p), w) = get_latency(&mut avg_latencies, &args, bytes); 47 | println!("{:?}b: [{:>5}ns, {:>5}ns, {:>5}ns]\t {:.1}", 48 | bytes, b, f, p, w); 49 | } 50 | 51 | 52 | 53 | println!("#elapsed {:?}", start_time.elapsed()); 54 | println!("bytes = {:?}", byte_sizes); 55 | let (base, others): (Vec<_>, Vec<_>) = avg_latencies 56 | .into_iter().map(|(b, f, p)| (b, (f, p))).unzip(); 57 | let (pre, post): (Vec<_>, Vec<_>) = others.into_iter().unzip(); 58 | println!("base = {:?}", base); 59 | println!("pre = {:?}", pre); 60 | println!("post = {:?}", post); 61 | } 62 | 63 | ///////////////////////// 64 | 65 | #[inline(never)] 66 | fn get_latency( 67 | avg_latencies: &mut Vec<(u32, u32, u32)>, args: &Args, level: u32, 68 | ) -> ((u32, u32, u32), u64) { 69 | let chain = order::from(level); 70 | let filtered = order::from(level + 1); 71 | let mut log = if let Some(tail_server) = args.tail_server { 72 | LogHandle::replicated_with_servers( 73 | iter::once((args.head_server, tail_server))) 74 | .chains(iter::once(chain).chain(iter::once(filtered))) 75 | .build() 76 | } else { 77 | LogHandle::unreplicated_with_servers(iter::once(args.head_server)) 78 | .chains(iter::once(chain).chain(iter::once(filtered))) 79 | .build() 80 | }; 81 | 82 | let bytes = vec![0xf; level as usize]; 83 | 84 | let write_start = Instant::now(); 85 | for (_, solo) in (0..100).zip(rand::thread_rng().gen_iter()) { 86 | if solo { 87 | log.async_append(chain, &bytes[..], &[]); 88 | } else { 89 | log.async_no_remote_multiappend(&[chain, filtered], &bytes[..], &[]); 90 | } 91 | } 92 | log.wait_for_all_appends().unwrap(); 93 | let write_time = write_start.elapsed(); 94 | println!("writes took {}.{:010}s", write_time.as_secs(), write_time.subsec_nanos()); 95 | 96 | let (base, pre, post): (u32, u32, u32); 97 | 98 | let mut latencies = Vec::with_capacity(args.num_rounds); 99 | 100 | let mut work = 0u64; 101 | 102 | { 103 | let mut record_latency = |chain, post_filter| { 104 | let mut expected_num_events = None; 105 | for _ in 0..args.num_rounds { 106 | let mut num_events = 0; 107 | let start_time = Instant::now(); 108 | log.snapshot(chain); 109 | 'recv1: loop { 110 | let next = log.get_next(); 111 | match next { 112 | Ok((b, locs)) if post_filter => if locs.len() != 1 { 113 | work = work.wrapping_add(b.iter().fold(0, 114 | |a, &b| a.wrapping_add(b as u64))); 115 | num_events += 1; 116 | }, 117 | Ok((b, _)) =>{ 118 | work = work.wrapping_add(b.iter().fold(0, 119 | |a, &b| a.wrapping_add(b as u64))); 120 | num_events += 1; 121 | }, 122 | Err(GetRes::Done) => break 'recv1, 123 | Err(r) => panic!("{:?}", r), 124 | } 125 | } 126 | expected_num_events.map(|e| assert_eq!(num_events, e)); 127 | expected_num_events = Some(num_events); 128 | let lat = start_time.elapsed(); 129 | latencies.push(lat); 130 | log.rewind(OrderIndex(chain.into(), 1.into())) 131 | } 132 | 133 | let sum: Duration = latencies.drain(..).sum(); 134 | let avg: Duration = sum / (args.num_rounds as u32); 135 | assert_eq!(avg.as_secs(), 0); 136 | avg.subsec_nanos() 137 | }; 138 | 139 | base = record_latency(chain, false); 140 | pre = record_latency(filtered, false); 141 | post = record_latency(chain, true); 142 | } 143 | 144 | avg_latencies.push((base, pre, post)); 145 | 146 | ((base, pre, post), work) 147 | } 148 | -------------------------------------------------------------------------------- /fuzzy_views/view_builder/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "view_builder" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | bincode = "0.8.0" 8 | fuzzy_log_client = {path = "../../fuzzy_log_client"} 9 | serde = "1" 10 | 11 | [dev-dependencies] 12 | fuzzy_log_server = {path = "../../fuzzy_log_server"} 13 | matches = "0.1.6" 14 | serde_derive = "1" 15 | -------------------------------------------------------------------------------- /fuzzylog.h: -------------------------------------------------------------------------------- 1 | #ifndef FuzzyLog_C_bindings_h 2 | #define FuzzyLog_C_bindings_h 3 | 4 | /* Generated with cbindgen:0.6.3 */ 5 | 6 | /* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | typedef struct DAG DAG; 13 | 14 | typedef struct HashMap_order__entry HashMap_order__entry; 15 | 16 | typedef HashMap_order__entry SnapBody; 17 | 18 | typedef SnapBody *SnapId; 19 | 20 | typedef DAG *FLPtr; 21 | 22 | /* 23 | * A `ColorSpec` describes the layout of a color. 24 | * 25 | * members: 26 | * local_chain: the local chain for this color 27 | * num_remote_chains: The number of remote chains which make up the color 28 | * retmote_chains: an array of size `numchains` consisting of the chains for a 29 | * color. 30 | * 31 | * NOTE `local_chain` _may_ be included in `remote_chains` as well, 32 | * though it is not necessary to do so. 33 | */ 34 | typedef struct { 35 | uint64_t local_chain; 36 | uintptr_t num_remote_chains; 37 | uint64_t *remote_chains; 38 | } ColorSpec; 39 | 40 | /* 41 | * The specification for a static FuzzyLog server configuration. 42 | * Since we're using chain-replication, in a replicated setup the client 43 | * needs to know of both the head and tail of each replication chain. In an 44 | * non-replicated setup tail_ips should be NULL. Each element of an ip 45 | * array should be in the form `:`. Currently only ipv4 is 46 | * supported. 47 | * 48 | * members: 49 | * num_ips: the number of IP addresses in each array 50 | * head_ips: an array of `":"` describing the heads of the 51 | * FuzzyLog replication chain. 52 | * tail_ips: an array of `":"` describing the heads of the 53 | * FuzzyLog replication chain, or `NULL` if the FuzzyLog is not 54 | * replicated/ 55 | */ 56 | typedef struct { 57 | uintptr_t num_ips; 58 | char **head_ips; 59 | char **tail_ips; 60 | } ServerSpec; 61 | 62 | void delete_snap_id(SnapId snap); 63 | 64 | /* 65 | * Append a node to the FuzzyLog 66 | * 67 | * args: 68 | * handle: the client handle which will perform the append 69 | * 70 | * data: the data to be contained in the new node 71 | * data_size: the number of bytes in `data` 72 | * 73 | * colors: the colors the new node should inhabit. Note that only 74 | * `local_color` will be read from these colors. 75 | * num_colors: the number of colors in `colors` 76 | */ 77 | int32_t fuzzylog_append(FLPtr handle, 78 | const char *data, 79 | uintptr_t data_size, 80 | const ColorSpec *colors, 81 | uintptr_t num_colors); 82 | 83 | void fuzzylog_close(FLPtr handle); 84 | 85 | /* 86 | * Sync a local view with the FuzzyLog. 87 | * 88 | * args: 89 | * handle: the client handle which will perform the sync 90 | * callback: a callback which will be called on every new event. 91 | * args are: the passed in `callback_state`, the event's `data`, 92 | * the events `data_size` 93 | * callback_state: a pointer passed as the first argument to callback. 94 | * May be `NULL`. 95 | */ 96 | SnapId fuzzylog_sync(FLPtr handle, 97 | void (*callback)(void*, const char*, uintptr_t), 98 | void *callback_state); 99 | 100 | void fuzzylog_trim(FLPtr handle, SnapId snap); 101 | 102 | /* 103 | * Start a new FuzzyLog client instance, and connect it so the supplied 104 | * server(s). 105 | * 106 | * args: 107 | * servers: a `ServerSpec` describing the servers to connect to. 108 | * color: a `ColorSpec` for the color this client reads. 109 | * snap: a SnapId that the client should start `sync`ing from, 110 | * or NULL if the client should start from the beginning of its 111 | * color 112 | */ 113 | FLPtr new_fuzzylog_instance(ServerSpec servers, ColorSpec color, SnapId snap); 114 | 115 | #endif /* FuzzyLog_C_bindings_h */ 116 | -------------------------------------------------------------------------------- /fuzzylog_async_ext.h: -------------------------------------------------------------------------------- 1 | #ifndef FuzzyLog_C_async_ext_h 2 | #define FuzzyLog_C_async_ext_h 3 | 4 | /* Generated with cbindgen:0.6.3 */ 5 | 6 | /* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | typedef struct { 14 | uint8_t bytes[16]; 15 | } WriteId; 16 | 17 | typedef struct { 18 | const WriteId *id; 19 | const char *data; 20 | uintptr_t data_size; 21 | const void *inhabits; 22 | uintptr_t inhabits_len; 23 | } FuzzyLogEvent; 24 | 25 | /* 26 | * Asynchronously append a node to the FuzzyLog. 27 | * Unlike `fuzzylog_append` this function does not wait for the append to 28 | * be ack'd by the server, but rather return immediately with a WriteId 29 | * which can be used to wait for the ack at a latter point in time. 30 | * 31 | * args: 32 | * handle: the client handle which will perform the append 33 | * 34 | * data: the data to be contained in the new node 35 | * data_size: the number of bytes in `data` 36 | * 37 | * colors: the colors the new node should inhabit. Note that only 38 | * `local_color` will be read from these colors. 39 | * num_colors: the number of colors in `colors` 40 | */ 41 | WriteId fuzzylog_async_append(FLPtr handle, 42 | const char *data, 43 | uintptr_t data_size, 44 | const ColorSpec *colors, 45 | uintptr_t num_colors); 46 | 47 | bool fuzzylog_event_inhabits_chain(FuzzyLogEvent event, uint64_t chain); 48 | 49 | /* 50 | * Sync a local view with the FuzzyLog. 51 | * 52 | * args: 53 | * handle: the client handle which will perform the sync 54 | * callback: a callback which will be called on every new event. 55 | * args are: the passed in `callback_state`, the event's `data`, 56 | * the events `data_size` 57 | * callback_state: a pointer passed as the first argument to callback. 58 | * May be `NULL`. 59 | */ 60 | SnapId fuzzylog_sync_events(FLPtr handle, 61 | void (*callback)(void*, FuzzyLogEvent), 62 | void *callback_state); 63 | 64 | /* 65 | * Check if any append written by this client has been ack'd by the server 66 | * return WriteId{0} if no such append exists. 67 | */ 68 | WriteId fuzzylog_try_wait_for_any_append(FLPtr handle); 69 | 70 | /* 71 | * Wait for a specific append sent by this client to be ack'd by the server. 72 | */ 73 | void fuzzylog_wait_for_a_specific_append(FLPtr handle, WriteId write_id); 74 | 75 | /* 76 | * Wait for all outstanding appends to be ack'd by the server. 77 | */ 78 | void fuzzylog_wait_for_all_appends(FLPtr handle); 79 | 80 | /* 81 | * Wait for any append sent by this client to be ack'd by the server. 82 | */ 83 | WriteId fuzzylog_wait_for_any_append(FLPtr handle); 84 | 85 | #endif /* FuzzyLog_C_async_ext_h */ 86 | -------------------------------------------------------------------------------- /get_ips.py: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/python2.7 2 | import boto3 3 | 4 | ec2client = boto3.client('ec2') 5 | response = ec2client.describe_instances() 6 | public_dns = [] 7 | private_ip = [] 8 | clients = [] 9 | servers = [] 10 | for reservation in response["Reservations"]: 11 | for instance in reservation["Instances"]: 12 | if instance[u'PublicDnsName'] != "": 13 | public_dns.append(instance[u'PublicDnsName']) 14 | private_ip.append(instance[u'PrivateIpAddress']) 15 | 16 | num_instances = len(private_ip) 17 | print(num_instances) 18 | num_clients = num_instances / 2 19 | #num_clients = 4 20 | 21 | print(public_dns) 22 | print(len(public_dns)) 23 | print("") 24 | print("") 25 | print("Clients") 26 | print(public_dns[0:num_clients]) 27 | print("") 28 | print("Servers") 29 | print(public_dns[num_clients:]) 30 | print(private_ip[num_clients:]) 31 | print("") 32 | print("") 33 | print("Client Hosts") 34 | server_ips = "" 35 | for i in range(0, len(private_ip[num_clients:]), 2): 36 | server_ips = server_ips + private_ip[num_clients + i] + ":13289#" + private_ip[num_clients + i + 1] + ":13289^" 37 | print(server_ips) 38 | client_hosts = "" 39 | for client in public_dns[0:num_clients]: 40 | client_hosts = client_hosts + client + "," 41 | print(client_hosts) 42 | 43 | -------------------------------------------------------------------------------- /packet-macro2/.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /packet-macro2/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "packet-macro2" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | packet-macro-impl = {path = "./packet-macro-impl"} 8 | -------------------------------------------------------------------------------- /packet-macro2/packet-macro-impl/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "packet-macro-impl" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | syn = "0.11.9" 8 | synom = "0.11.3" 9 | quote = "0.3.15" 10 | 11 | [lib] 12 | proc-macro = true 13 | 14 | [features] 15 | default = ["syn/full"] 16 | -------------------------------------------------------------------------------- /packet-macro2/packet-macro-impl/src/parser.rs: -------------------------------------------------------------------------------- 1 | //use Packet; 2 | //use PacketBody; 3 | 4 | use syn::{Ident, Expr}; 5 | use syn::parse::ident as ident; 6 | use syn::parse::expr as expr; 7 | 8 | // a hacked version of the syn parsers which allows for an enlarged type syntax 9 | 10 | #[derive(Debug, Clone)] 11 | pub enum PacketBody { 12 | Struct(Vec), 13 | Enum(KindFlag, Vec), 14 | } 15 | 16 | #[derive(Debug, Clone)] 17 | pub struct KindFlag(pub Ident, pub Ty); 18 | 19 | #[derive(Debug, Clone)] 20 | pub struct Variant { 21 | pub ident: Ident, 22 | pub flag: Expr, 23 | pub body: Vec, 24 | } 25 | 26 | #[derive(Debug, Clone)] 27 | pub struct Field { 28 | pub ident: Ident, 29 | pub ty: Ty, 30 | } 31 | 32 | #[derive(Debug, Clone)] 33 | pub enum Ty { 34 | Path(bool, Vec), 35 | Array(Box, Expr), 36 | VarArray(Box, Ident), 37 | Tuple(Vec), 38 | } 39 | 40 | #[derive(Debug, Clone)] 41 | pub enum PathFragment { 42 | Fish(Ident, Ident), 43 | Ident(Ident), 44 | } 45 | 46 | 47 | named!(pub packet_body -> PacketBody, do_parse!( 48 | which: alt!(keyword!("struct") | keyword!("enum")) >> 49 | item: switch!(value!(which), 50 | "struct" => map!(struct_like_body, move |body| PacketBody::Struct(body)) 51 | | 52 | "enum" => map!(enum_body, move |(kind, body)| PacketBody::Enum(kind, body)) 53 | ) >> 54 | (item) 55 | )); 56 | 57 | named!(pub enum_body -> (KindFlag, Vec), do_parse!( 58 | punct!("{") >> 59 | kind_name: ident >> 60 | //call!(inspect, "after tag id") >> 61 | punct!(":") >> 62 | kind_type: ty >> 63 | punct!(",") >> 64 | variants: terminated_list!(punct!(","), variant) >> 65 | punct!("}") >> 66 | (KindFlag(kind_name, kind_type), variants) 67 | )); 68 | 69 | named!(variant -> Variant, do_parse!( 70 | id: ident >> 71 | punct!(":") >> 72 | flag: expr >> 73 | punct!("=>") >> 74 | body: struct_like_body >> 75 | (Variant { 76 | ident: id, 77 | flag: flag, 78 | body: body, 79 | }) 80 | )); 81 | 82 | named!(pub struct_like_body -> Vec, do_parse!( 83 | punct!("{") >> 84 | fields: terminated_list!(punct!(","), struct_field) >> 85 | punct!("}") >> 86 | (fields) 87 | )); 88 | 89 | named!(struct_field -> Field, do_parse!( 90 | id: ident >> 91 | punct!(":") >> 92 | ty: ty >> 93 | (Field { 94 | ident: id, 95 | ty: ty, 96 | }) 97 | )); 98 | 99 | named!(pub ty -> Ty, alt!( 100 | ty_paren // must be before ty_tup 101 | | 102 | ty_path // must be before ty_poly_trait_ref 103 | | 104 | ty_array 105 | | 106 | ty_var_len 107 | | 108 | ty_tup 109 | )); 110 | 111 | named!(ty_path -> Ty, do_parse!( 112 | global: option!(punct!("::")) >> 113 | path: separated_nonempty_list!(punct!("::"), ty_path_fragment) >> 114 | (Ty::Path(global.is_some(), path)) 115 | )); 116 | 117 | named!(ty_path_fragment -> PathFragment, alt!( 118 | ty_fish 119 | | 120 | ty_ident 121 | )); 122 | 123 | named!(ty_fish -> PathFragment, do_parse!( 124 | punct!("<") >> 125 | ident0: ident >> 126 | punct!("as") >> 127 | ident1: ident >> 128 | punct!("<") >> 129 | (PathFragment::Fish(ident0, ident1)) 130 | )); 131 | 132 | named!(ty_ident -> PathFragment, do_parse!( 133 | ident: ident >> 134 | (PathFragment::Ident(ident)) 135 | )); 136 | 137 | named!(ty_paren -> Ty, do_parse!( 138 | punct!("(") >> 139 | elem: ty >> 140 | punct!(")") >> 141 | (elem) 142 | )); 143 | 144 | named!(ty_array -> Ty, do_parse!( 145 | punct!("[") >> 146 | elem: ty >> 147 | punct!(";") >> 148 | len: expr >> 149 | punct!("]") >> 150 | (Ty::Array(Box::new(elem), len)) 151 | )); 152 | 153 | named!(ty_var_len -> Ty, do_parse!( 154 | punct!("[") >> 155 | elem: ty >> 156 | punct!("|") >> 157 | len: ident >> 158 | punct!("]") >> 159 | (Ty::VarArray(Box::new(elem), len)) 160 | )); 161 | 162 | named!(ty_tup -> Ty, do_parse!( 163 | punct!("(") >> 164 | elems: terminated_list!(punct!(","), ty) >> 165 | punct!(")") >> 166 | (Ty::Tuple(elems)) 167 | )); 168 | 169 | #[allow(dead_code)] 170 | fn inspect<'a>(input: &'a str, print: &str) -> ::synom::IResult<&'a str, ()> { 171 | println!("{:?}", print); 172 | ::synom::IResult::Done(&input, ()) 173 | } 174 | -------------------------------------------------------------------------------- /reactor/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "reactor" 3 | version = "0.1.0" 4 | authors = ["Joshua Lockerman <>"] 5 | 6 | [dependencies] 7 | fuzzy_log_util = {path = "../fuzzy_log_util"} 8 | fuzzy_log_packets = {path = "../fuzzy_log_packets"} 9 | log = "0.3" 10 | mio = "0.6.6" 11 | -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | #Scripts 2 | ##start_servers.sh 3 | ```sh 4 | ./start_servers.sh 5 | ``` 6 | 7 | This script will start a binary on servers found in a config file. 8 | The config file should be of the form 9 | ```sh 10 | DELOS_LOCK_SERVER= 11 | DELOS_CHAIN_SERVERS= 12 | ``` 13 | where `DELOS_CHAIN_SERVERS` contains a list of server ip addresses and ports at which the various chain servers should be started and if there are more than ine such server `DELOS_LOCK_SERVER` shall contain the ip address and port at which the lock server should be started. -------------------------------------------------------------------------------- /scripts/example_server_config: -------------------------------------------------------------------------------- 1 | DELOS_LOCK_SERVER="vmhost5.cloud.cs.yale.internal:13240" 2 | DELOS_CHAIN_SERVERS="vmhost5.cloud.cs.yale.internal:13241 vmhost5.cloud.cs.yale.internal:13242 vmhost5.cloud.cs.yale.internal:13243" 3 | 4 | -------------------------------------------------------------------------------- /scripts/mirror_on_servers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if (($# < 3)); then 4 | echo 5 | echo -e "\033[0;32mUsage\033[0m: ./mirror_on_servers.sh