Remove obsolete & duplicate documentation, etc
This commit is contained in:
parent
8487d5759d
commit
26f08e62ec
16 changed files with 48 additions and 25451 deletions
|
@ -23,7 +23,9 @@ We will also accept fixes for bugs in the test code.
|
|||
|
||||
## The chain-manager prototype
|
||||
|
||||
TODO
|
||||
This is a very early experiment to try to create a distributed "rough
|
||||
consensus" algorithm that is sufficient & safe for managing the order
|
||||
of a Chain Replication chain, its members, and its chain order.
|
||||
|
||||
## The corfurl prototype
|
||||
|
||||
|
|
1
prototype/chain-manager/.gitignore
vendored
1
prototype/chain-manager/.gitignore
vendored
|
@ -6,3 +6,4 @@ deps
|
|||
ebin/*.beam
|
||||
ebin/*.app
|
||||
erl_crash.dump
|
||||
RUNLOG*
|
||||
|
|
|
@ -41,3 +41,15 @@ concuerror: deps compile
|
|||
concuerror -m machi_flu0_test -t proj_store_test $(CONC_ARGS)
|
||||
concuerror -m machi_flu0_test -t wedge_test $(CONC_ARGS)
|
||||
concuerror -m machi_flu0_test -t proj0_test $(CONC_ARGS)
|
||||
|
||||
APPS = kernel stdlib sasl erts ssl compiler eunit
|
||||
PLT = $(HOME)/.chmgr_dialyzer_plt
|
||||
|
||||
build_plt: deps compile
|
||||
dialyzer --build_plt --output_plt $(PLT) --apps $(APPS) deps/*/ebin
|
||||
|
||||
dialyzer: deps compile
|
||||
dialyzer -Wno_return --plt $(PLT) ebin
|
||||
|
||||
clean_plt:
|
||||
rm $(PLT)
|
||||
|
|
15
prototype/chain-manager/README.md
Normal file
15
prototype/chain-manager/README.md
Normal file
|
@ -0,0 +1,15 @@
|
|||
# The chain-manager prototype
|
||||
|
||||
This is a very early experiment to try to create a distributed "rough
|
||||
consensus" algorithm that is sufficient & safe for managing the order
|
||||
of a Chain Replication chain, its members, and its chain order.
|
||||
|
||||
## Compilation & unit testing
|
||||
|
||||
Use `make` and `make test`. Note that the Makefile assumes that the
|
||||
`rebar` utility is available somewhere in your path.
|
||||
|
||||
Tested using Erlang/OTP R16B and Erlang/OTP 17, both on OS X.
|
||||
|
||||
It ought to "just work" on other versions of Erlang and on other OS
|
||||
platforms, but sorry, I haven't tested it.
|
2
prototype/chain-manager/docs/README.md
Normal file
2
prototype/chain-manager/docs/README.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
|
||||
Please see the `doc` directory at the top of the Machi repo.
|
|
@ -1,191 +0,0 @@
|
|||
## CORFU papers
|
||||
|
||||
I recommend the "5 pages" paper below first, to give a flavor of
|
||||
what the CORFU is about. When Scott first read the CORFU paper
|
||||
back in 2011 (and the Hyder paper), he thought it was insanity.
|
||||
He recommends waiting before judging quite so hastily. :-)
|
||||
|
||||
After that, then perhaps take a step back are skim over the
|
||||
Hyder paper. Hyder started before CORFU, but since CORFU, the
|
||||
Hyder folks at Microsoft have rewritten Hyder to use CORFU as
|
||||
the shared log underneath it. But the Hyder paper has lots of
|
||||
interesting bits about how you'd go about creating a distributed
|
||||
DB where the transaction log *is* the DB.
|
||||
|
||||
### "CORFU: A Distributed Shared LogCORFU: A Distributed Shared Log"
|
||||
|
||||
MAHESH BALAKRISHNAN, DAHLIA MALKHI, JOHN D. DAVIS, and VIJAYAN
|
||||
PRABHAKARAN, Microsoft Research Silicon Valley, MICHAEL WEI,
|
||||
University of California, San Diego, TED WOBBER, Microsoft Research
|
||||
Silicon Valley
|
||||
|
||||
Long version of introduction to CORFU (~30 pages)
|
||||
http://www.snookles.com/scottmp/corfu/corfu.a10-balakrishnan.pdf
|
||||
|
||||
### "CORFU: A Shared Log Design for Flash Clusters"
|
||||
|
||||
Same authors as above
|
||||
|
||||
Short version of introduction to CORFU paper above (~12 pages)
|
||||
|
||||
http://www.snookles.com/scottmp/corfu/corfu-shared-log-design.nsdi12-final30.pdf
|
||||
|
||||
### "From Paxos to CORFU: A Flash-Speed Shared Log"
|
||||
|
||||
Same authors as above
|
||||
|
||||
5 pages, a short summary of CORFU basics and some trial applications
|
||||
that have been implemented on top of it.
|
||||
|
||||
http://www.snookles.com/scottmp/corfu/paxos-to-corfu.malki-acmstyle.pdf
|
||||
|
||||
### "Beyond Block I/O: Implementing a Distributed Shared Log in Hardware"
|
||||
|
||||
Wei, Davis, Wobber, Balakrishnan, Malkhi
|
||||
|
||||
Summary report of implmementing the CORFU server-side in
|
||||
FPGA-style hardware. (~11 pages)
|
||||
|
||||
http://www.snookles.com/scottmp/corfu/beyond-block-io.CameraReady.pdf
|
||||
|
||||
### "Tango: Distributed Data Structures over a Shared Log"
|
||||
|
||||
Balakrishnan, Malkhi, Wobber, Wu, Brabhakaran, Wei, Davis, Rao, Zou, Zuck
|
||||
|
||||
Describes a framework for developing data structures that reside
|
||||
persistently within a CORFU log: the log *is* the database/data
|
||||
structure store.
|
||||
|
||||
http://www.snookles.com/scottmp/corfu/Tango.pdf
|
||||
|
||||
### "Dynamically Scalable, Fault-Tolerant Coordination on a Shared Logging Service"
|
||||
|
||||
Wei, Balakrishnan, Davis, Malkhi, Prabhakaran, Wobber
|
||||
|
||||
The ZooKeeper inter-server communication is replaced with CORFU.
|
||||
Faster, fewer lines of code than ZK, and more features than the
|
||||
original ZK code base.
|
||||
|
||||
http://www.snookles.com/scottmp/corfu/zookeeper-techreport.pdf
|
||||
|
||||
### "Hyder – A Transactional Record Manager for Shared Flash"
|
||||
|
||||
Bernstein, Reid, Das
|
||||
|
||||
Describes a distributed log-based DB system where the txn log is
|
||||
treated quite oddly: a "txn intent" record is written to a
|
||||
shared common log All participants read the shared log in
|
||||
parallel and make commit/abort decisions in parallel, based on
|
||||
what conflicts (or not) that they see in the log. Scott's first
|
||||
reading was "No way, wacky" ... and has since changed his mind.
|
||||
|
||||
http://www.snookles.com/scottmp/corfu/CIDR2011Proceedings.pdf
|
||||
pages 9-20
|
||||
|
||||
|
||||
|
||||
## Fiddling with PULSE
|
||||
|
||||
Do the following:
|
||||
|
||||
make clean
|
||||
make
|
||||
make pulse
|
||||
|
||||
... then watch the dots go across the screen for 60 seconds. If you
|
||||
wish, you can press `Control-c` to interrupt the test. We're really
|
||||
interested in the build artifacts.
|
||||
|
||||
erl -pz .eunit deps/*/ebin
|
||||
eqc:quickcheck(eqc:testing_time(5, corfurl_pulse:prop_pulse())).
|
||||
|
||||
This will run the PULSE test for 5 seconds. Feel free to adjust for
|
||||
as many seconds as you wish.
|
||||
|
||||
Erlang R16B02-basho4 (erts-5.10.3) [source] [64-bit] [smp:8:8] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]
|
||||
|
||||
Eshell V5.10.3 (abort with ^G)
|
||||
1> eqc:quickcheck(eqc:testing_time(5, corfurl_pulse:prop_pulse())).
|
||||
Starting Quviq QuickCheck version 1.30.4
|
||||
(compiled at {{2014,2,7},{9,19,50}})
|
||||
Licence for Basho reserved until {{2014,2,17},{1,41,39}}
|
||||
......................................................................................
|
||||
OK, passed 86 tests
|
||||
schedule: Count: 86 Min: 2 Max: 1974 Avg: 3.2e+2 Total: 27260
|
||||
true
|
||||
2>
|
||||
|
||||
REPL interactive work can be done via:
|
||||
|
||||
1. Edit code, e.g. `corfurl_pulse.erl`.
|
||||
2. Run `env BITCASK_PULSE=1 ./rebar skip_deps=true -D PULSE eunit suites=SKIP`
|
||||
to compile.
|
||||
3. Reload any recompiled modules, e.g. `l(corfurl_pulse).`
|
||||
4. Resume QuickCheck activities.
|
||||
|
||||
## Seeing an PULSE scheduler interleaving failure in action
|
||||
|
||||
1. Edit `corfurl_pulse:check_trace()` to uncomment the
|
||||
use of `conjunction()` that mentions `bogus_order_check_do_not_use_me`
|
||||
and comment out the real `conjunction()` call below it.
|
||||
2. Recompile & reload.
|
||||
3. Check.
|
||||
|
||||
For example:
|
||||
|
||||
9> eqc:quickcheck(eqc:testing_time(5, corfurl_pulse:prop_pulse())).
|
||||
.........Failed! After 9 tests.
|
||||
|
||||
Sweet! The first tuple below are the first `?FORALL()` values,
|
||||
and the 2nd is the list of commands,
|
||||
`{SequentialCommands, ListofParallelCommandLists}`. The 3rd is the
|
||||
seed used to perturb the PULSE scheduler.
|
||||
|
||||
In this case, `SequentialCommands` has two calls (to `setup()` then
|
||||
`append()`) and there are two parallel procs: one makes 1 call
|
||||
call to `append()` and the other makes 2 calls to `append()`.
|
||||
|
||||
{2,2,9}
|
||||
{{[{set,{var,1},{call,corfurl_pulse,setup,[2,2,9]}}],
|
||||
[[{set,{var,3},
|
||||
{call,corfurl_pulse,append,
|
||||
[{var,1},<<231,149,226,203,10,105,54,223,147>>]}}],
|
||||
[{set,{var,2},
|
||||
{call,corfurl_pulse,append,
|
||||
[{var,1},<<7,206,146,75,249,13,154,238,110>>]}},
|
||||
{set,{var,4},
|
||||
{call,corfurl_pulse,append,
|
||||
[{var,1},<<224,121,129,78,207,23,79,216,36>>]}}]]},
|
||||
{27492,46961,4884}}
|
||||
|
||||
Here are our results:
|
||||
|
||||
simple_result: passed
|
||||
errors: passed
|
||||
events: failed
|
||||
identity: passed
|
||||
bogus_order_check_do_not_use_me: failed
|
||||
[{ok,1},{ok,3},{ok,2}] /= [{ok,1},{ok,2},{ok,3}]
|
||||
|
||||
Our (bogus!) order expectation was violated. Shrinking!
|
||||
|
||||
simple_result: passed
|
||||
errors: passed
|
||||
events: failed
|
||||
identity: passed
|
||||
bogus_order_check_do_not_use_me: failed
|
||||
[{ok,1},{ok,3},{ok,2}] /= [{ok,1},{ok,2},{ok,3}]
|
||||
|
||||
Shrinking was able to remove two `append()` calls and to shrink the
|
||||
size of the pages down from 9 bytes down to 1 byte.
|
||||
|
||||
Shrinking........(8 times)
|
||||
{1,1,1}
|
||||
{{[{set,{var,1},{call,corfurl_pulse,setup,[1,1,1]}}],
|
||||
[[{set,{var,3},{call,corfurl_pulse,append,[{var,1},<<0>>]}}],
|
||||
[{set,{var,4},{call,corfurl_pulse,append,[{var,1},<<0>>]}}]]},
|
||||
{27492,46961,4884}}
|
||||
events: failed
|
||||
bogus_order_check_do_not_use_me: failed
|
||||
[{ok,2},{ok,1}] /= [{ok,1},{ok,2}]
|
||||
false
|
|
@ -1,35 +0,0 @@
|
|||
msc {
|
||||
client1, FLU1, FLU2, client2, client3;
|
||||
|
||||
client1 box client3 [label="Epoch #1: chain = FLU1 -> FLU2"];
|
||||
client1 -> FLU1 [label="{write,epoch1,<<Page YYY>>}"];
|
||||
client1 <- FLU1 [label="ok"];
|
||||
client1 box client1 [label="Client crash", textcolour="red"];
|
||||
|
||||
FLU1 box FLU1 [label="FLU crash", textcolour="red"];
|
||||
|
||||
client1 box client3 [label="Epoch #2: chain = FLU2"];
|
||||
|
||||
client2 -> FLU2 [label="{write,epoch2,<<Page ZZZ>>}"];
|
||||
client2 <- FLU2 [label="ok"];
|
||||
|
||||
client3 box client3 [label="Read repair starts", textbgcolour="aqua"];
|
||||
|
||||
client3 -> FLU2 [label="{read,epoch2}"];
|
||||
client3 <- FLU2 [label="{ok,<<Page ZZZ>>}"];
|
||||
client3 -> FLU1 [label="{write,epoch2,<<Page ZZZ>>}"];
|
||||
FLU1 box FLU1 [label="What do we do here? Our current value is <<Page YYY>>.", textcolour="red"] ;
|
||||
FLU1 box FLU1 [label="If we do not accept the repair value, then we are effectively UNREPAIRABLE.", textcolour="red"] ;
|
||||
FLU1 box FLU1 [label="If we do accept the repair value, then we are mutating an already-written value.", textcolour="red"] ;
|
||||
FLU1 -> client3 [label="I'm sorry, Dave, I cannot do that."];
|
||||
|
||||
FLU1 box FLU1 [label = "In theory, while repair is still happening, nobody will ever ask FLU1 for its value.", textcolour="black"] ;
|
||||
|
||||
client3 -> FLU1 [label="{write,epoch2,<<Page ZZZ>>,repair,witnesses=[FLU2]}", textbgcolour="silver"];
|
||||
FLU1 box FLU1 [label="Start an async process to ask the witness list to corroborate this repair."];
|
||||
FLU1 -> FLU2 [label="{read,epoch2}", textbgcolour="aqua"];
|
||||
FLU1 <- FLU2 [label="{ok,<<Page ZZ>>}", textbgcolour="aqua"];
|
||||
FLU1 box FLU1 [label="Overwrite local storage with repair page.", textbgcolour="silver"];
|
||||
client3 <- FLU1 [label="Async proc replies: ok", textbgcolour="silver"];
|
||||
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
|
||||
## read-repair-race.1.
|
||||
|
||||
First attempt at using "mscgen" to make some Message Sequence
|
||||
Chart (MSC) for a race found at commit 087c2605ab.
|
||||
|
||||
|
||||
## read-repair-race.2.
|
||||
|
||||
Second attempt. This is almost exactly the trace that is
|
||||
generated by this failing test case at commit 087c2605ab:
|
||||
|
||||
C2 = [{1,2,1},{{[{set,{var,1},{call,corfurl_pulse,setup,[1,2,1,standard]}}],[[{set,{var,3},{call,corfurl_pulse,append,[{var,1},<<0>>]}}],[{set,{var,2},{call,corfurl_pulse,read_approx,[{var,1},6201864198]}},{set,{var,5},{call,corfurl_pulse,append,[{var,1},<<0>>]}}],[{set,{var,4},{call,corfurl_pulse,append,[{var,1},<<0>>]}},{set,{var,6},{call,corfurl_pulse,trim,[{var,1},510442857]}}]]},{25152,1387,78241}},[{events,[[{no_bad_reads,[]}]]}]].
|
||||
eqc:check(corfurl_pulse:prop_pulse(), C2).
|
||||
|
||||
## read-repair-race.2b.*
|
||||
|
||||
Same basic condition as read-repair-race.2, but edited
|
||||
substantially to make it clearer what is happening.
|
||||
Also for commit 087c2605ab.
|
||||
|
||||
I believe that I have a fix for the silver-colored
|
||||
`error-overwritten` ... and it was indeed added to the code soon
|
||||
afterward, but it turns out that it doesn't solve the entire problem
|
||||
of "two clients try to write the exact same data at the same time to
|
||||
the same LPN".
|
||||
|
||||
|
||||
## "Two Clients Try to Write the Exact Same Data at the Same Time to the Same LPN"
|
||||
|
||||
This situation is something that CORFU cannot protect against, IMO.
|
||||
|
||||
I have been struggling for a while, to try to find a way for CORFU
|
||||
clients to know *always* when there is a conflict with another
|
||||
writer. It usually works: the basic nature of write-once registers is
|
||||
very powerful. However, in the case where two clients are trying to
|
||||
write the same page data to the same LPN, it looks impossible to
|
||||
resolve.
|
||||
|
||||
How do you tell the difference between:
|
||||
|
||||
1. A race between a client A writing page P at address LPN and
|
||||
read-repair fixing P. P *is* A's data and no other's, so this race
|
||||
doesn't confuse anyone.
|
||||
|
||||
1. A race between a client A writing page P at address LPN and client
|
||||
B writing the exact same page data P at the same LPN.
|
||||
A's page P = B's page P, but clients A & B don't know that.
|
||||
|
||||
If CORFU tells both A & B that they were successful, A & B assume
|
||||
that the CORFU log has two new pages appended to it, but in truth
|
||||
only one new page was appended.
|
||||
|
||||
If we try to solve this by always avoiding the same LPN address
|
||||
conflict, we are deluding ourselves. If we assume that the sequencer
|
||||
is 100% correct in that it never assigns the same LPN twice, and if we
|
||||
assume that a client must never write a block without an assignment
|
||||
from the sequencer, then the problem is solved. But the problem has a
|
||||
_heavy_ price: the log is only available when the sequencer is
|
||||
available, and only when never more than one sequencer running at a
|
||||
time.
|
||||
|
||||
The CORFU base system promises correct operation, even if:
|
||||
|
||||
* Zero sequencers are running, and clients might choose the same LPN
|
||||
to write to.
|
||||
* Two more more sequencers are running, and different sequencers
|
||||
assign the same LPN to two different clients.
|
||||
|
||||
But CORFU's "correct" behavior does not include detecting the same
|
||||
page at the same LPN. The papers don't specifically say it, alas.
|
||||
But IMO it's impossible to guarantee, so all docs ought to explicitly
|
||||
say that it's impossible and that clients must not assume it.
|
||||
|
||||
See also
|
||||
* two-clients-race.1.png
|
||||
|
||||
## A scenario of chain repair & write-once registers
|
||||
|
||||
See:
|
||||
* 2014-02-27.chain-repair-write-twice.png
|
||||
|
||||
... for a scenario where write-once registers that are truly only
|
||||
write-once-ever-for-the-rest-of-the-future are "inconvenient" when it
|
||||
comes to chain repair. Client 3 is attempting to do chain repair ops,
|
||||
bringing FLU1 back into sync with FLU2.
|
||||
|
||||
The diagram proposes one possible idea for making overwriting a
|
||||
read-once register a bit safer: ask another node in the chain to
|
||||
verify that the page you've been asked to repair is exactly the same
|
||||
as that other FLU's page.
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
msc {
|
||||
"<0.12583.0>" [label="Client1"], "<0.12574.0>" [label="FLU1"], "<0.12575.0>" [label="FLU2"], "<0.12576.0>" [label="FLU3"], "<0.12584.0>" [label="Client2"], "<0.12585.0>" [label="Client3"];
|
||||
|
||||
"<0.12585.0>" -> "<0.12576.0>" [ label = "{read,1,1}" ] ;
|
||||
"<0.12583.0>" -> "<0.12574.0>" [ label = "{write,1,1,<<0>>}" ] ;
|
||||
"<0.12576.0>" -> "<0.12585.0>" [ label = "error_unwritten" ] ;
|
||||
"<0.12585.0>" abox "<0.12585.0>" [ label="Read Repair starts", textbgcolour="yellow"];
|
||||
"<0.12585.0>" -> "<0.12574.0>" [ label = "{read,1,1}" ] ;
|
||||
"<0.12574.0>" -> "<0.12583.0>" [ label = "ok" ] ;
|
||||
"<0.12583.0>" -> "<0.12575.0>" [ label = "{write,1,1,<<0>>}" ] ;
|
||||
"<0.12574.0>" -> "<0.12585.0>" [ label = "{ok,<<0>>}" ,textcolour="red"] ;
|
||||
"<0.12585.0>" -> "<0.12575.0>" [ label = "{write,1,1,<<0>>}" ] ;
|
||||
"<0.12575.0>" -> "<0.12585.0>" [ label = "ok" ] ;
|
||||
"<0.12585.0>" -> "<0.12576.0>" [ label = "{write,1,1,<<0>>}" ] ;
|
||||
"<0.12575.0>" -> "<0.12583.0>" [ label = "error_overwritten" ] ;
|
||||
"<0.12583.0>" abox "<0.12583.0>" [ label = "Race with read repair? Read to double-check", textbgcolour="yellow" ] ;
|
||||
"<0.12583.0>" -> "<0.12575.0>" [ label = "{read,1,1}" ] ;
|
||||
"<0.12576.0>" -> "<0.12585.0>" [ label = "ok" ] ;
|
||||
"<0.12585.0>" abox "<0.12585.0>" [ label="Read Repair SUCCESS", textbgcolour="green"];
|
||||
"<0.12585.0>" abox "<0.12585.0>" [ label="Our problem: the PULSE model never believes that append_page ever wrote LPN 1", textcolour="red"];
|
||||
"<0.12584.0>" abox "<0.12584.0>" [ label = "Client2 decides to trim LPN 1", textbgcolour="orange" ] ;
|
||||
"<0.12584.0>" -> "<0.12574.0>" [ label = "{trim,1,1}" ] ;
|
||||
"<0.12575.0>" -> "<0.12583.0>" [ label = "{ok,<<0>>}"] ;
|
||||
"<0.12583.0>" abox "<0.12583.0>" [ label = "Value matches, yay!", textbgcolour="yellow" ] ;
|
||||
"<0.12583.0>" abox "<0.12583.0>" [ label = "Continue writing", textbgcolour="yellow" ] ;
|
||||
"<0.12583.0>" -> "<0.12576.0>" [ label = "{write,1,1,<<0>>}" ] ;
|
||||
"<0.12574.0>" -> "<0.12584.0>" [ label = "ok" ] ;
|
||||
"<0.12584.0>" -> "<0.12575.0>" [ label = "{trim,1,1}" ] ;
|
||||
"<0.12576.0>" -> "<0.12583.0>" [ label = "error_overwritten" ] ;
|
||||
"<0.12583.0>" abox "<0.12583.0>" [ label = "Race with read repair? Read to double-check", textbgcolour="yellow" ] ;
|
||||
"<0.12583.0>" -> "<0.12576.0>" [ label = "{read,1,1}" ] ;
|
||||
"<0.12575.0>" -> "<0.12584.0>" [ label = "ok" ] ;
|
||||
"<0.12584.0>" -> "<0.12576.0>" [ label = "{trim,1,1}" ] ;
|
||||
"<0.12576.0>" -> "<0.12584.0>" [ label = "ok" ] ;
|
||||
"<0.12576.0>" -> "<0.12583.0>" [ label = "error_trimmed" ] ;
|
||||
"<0.12583.0>" abox "<0.12583.0>" [ label = "Value MISMATCH!", textcolour="red" ] ;
|
||||
"<0.12583.0>" abox "<0.12583.0>" [ label = "Read repair", textbgcolour="yellow" ] ;
|
||||
"<0.12583.0>" -> "<0.12574.0>" [ label = "{read,1,1}" ] ;
|
||||
"<0.12574.0>" -> "<0.12583.0>" [ label = "error_trimmed" ] ;
|
||||
"<0.12583.0>" -> "<0.12575.0>" [ label = "{fill,1,1}" ] ;
|
||||
"<0.12575.0>" -> "<0.12583.0>" [ label = "error_trimmed" ] ;
|
||||
"<0.12583.0>" -> "<0.12576.0>" [ label = "{fill,1,1}" ] ;
|
||||
"<0.12576.0>" -> "<0.12583.0>" [ label = "error_trimmed" ] ;
|
||||
"<0.12583.0>" abox "<0.12583.0>" [ label = "At this point, we give up on LPN 1.", textcolour="red" ] ;
|
||||
"<0.12583.0>" abox "<0.12583.0>" [ label = "Sequencer gives us LPN 2", textbgcolour="yellow" ] ;
|
||||
"<0.12583.0>" abox "<0.12583.0>" [ label = "LPN 2 has been filled (not shown).", textbgcolour="yellow" ] ;
|
||||
"<0.12583.0>" abox "<0.12583.0>" [ label = "Sequencer gives us LPN 3", textbgcolour="yellow" ] ;
|
||||
"<0.12583.0>" abox "<0.12583.0>" [ label = "We write LPN 3 successfully", textbgcolour="green" ] ;
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
msc {
|
||||
"<0.32555.4>" [label="Client1"], "<0.32551.4>" [label="FLU1"], "<0.32552.4>" [label="FLU2"], "<0.32556.4>" [label="Client2"], "<0.32557.4>" [label="Client3"];
|
||||
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "Writer", textbgcolour="orange"],
|
||||
"<0.32556.4>" abox "<0.32556.4>" [ label = "Reader", textbgcolour="orange"],
|
||||
"<0.32557.4>" abox "<0.32557.4>" [ label = "Trimmer", textbgcolour="orange"];
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "append_page()", textbgcolour="yellow"] ;
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "Sequencer assigns LPN 1", textbgcolour="yellow"] ;
|
||||
"<0.32555.4>" -> "<0.32551.4>" [ label = "{write,1,1,<<0>>}" ] ;
|
||||
"<0.32556.4>" abox "<0.32556.4>" [ label = "read_page(LPN 1)", textbgcolour="yellow"] ;
|
||||
"<0.32556.4>" -> "<0.32552.4>" [ label = "{read,1,1}" ] ;
|
||||
"<0.32552.4>" -> "<0.32556.4>" [ label = "error_unwritten" ] ;
|
||||
"<0.32556.4>" abox "<0.32556.4>" [ label = "Start read repair", textbgcolour="aqua"] ;
|
||||
"<0.32556.4>" -> "<0.32551.4>" [ label = "{read,1,1}" ] ;
|
||||
"<0.32551.4>" -> "<0.32555.4>" [ label = "ok" ] ;
|
||||
"<0.32551.4>" -> "<0.32556.4>" [ label = "{ok,<<0>>}" ] ;
|
||||
"<0.32556.4>" -> "<0.32552.4>" [ label = "{write,1,1,<<0>>}" ] ;
|
||||
"<0.32555.4>" -> "<0.32552.4>" [ label = "{write,1,1,<<0>>}" ] ;
|
||||
"<0.32557.4>" -> "<0.32551.4>" [ label = "{trim,1,1}" ] ;
|
||||
"<0.32552.4>" -> "<0.32555.4>" [ label = "error_overwritten" ] ;
|
||||
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "Our attempt to write LPN 1 is interrupted", textbgcolour="yellow"] ;
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "Check if an eager read-repair has written our data for us.", textbgcolour="yellow"] ;
|
||||
"<0.32555.4>" -> "<0.32552.4>" [ label = "{read,1,1}" ] ;
|
||||
"<0.32551.4>" -> "<0.32557.4>" [ label = "ok" ] ;
|
||||
"<0.32552.4>" -> "<0.32556.4>" [ label = "ok" ] ;
|
||||
"<0.32556.4>" abox "<0.32556.4>" [ label = "End read repair", textbgcolour="aqua"] ;
|
||||
"<0.32556.4>" abox "<0.32556.4>" [ label = "read_page(LPN 1) -> {ok, <<0>>}", textbgcolour="yellow"] ;
|
||||
"<0.32556.4>" abox "<0.32556.4>" [ label = "See red stuff at bottom....", textcolour="red"] ;
|
||||
# "<0.32556.4>" abox "<0.32556.4>" [ label = "But PULSE thinks that LPN 1 was never written.", textcolour="red"] ;
|
||||
# "<0.32556.4>" abox "<0.32556.4>" [ label = "Fixing this requires ... lots of pondering...", textcolour="red"] ;
|
||||
"<0.32557.4>" -> "<0.32552.4>" [ label = "{trim,1,1}" ] ;
|
||||
"<0.32552.4>" -> "<0.32557.4>" [ label = "ok" ] ;
|
||||
"<0.32552.4>" -> "<0.32555.4>" [ label = "error_trimmed" ] ;
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "Wow, an eager trimmer got us, ouch.", textbgcolour="yellow"] ;
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "Start read repair", textbgcolour="aqua"] ;
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "Read repair here is for sanity checking, not really necessary.", textbgcolour="yellow"] ;
|
||||
"<0.32555.4>" -> "<0.32551.4>" [ label = "{read,1,1}" ] ;
|
||||
"<0.32551.4>" -> "<0.32555.4>" [ label = "error_trimmed" ] ;
|
||||
"<0.32555.4>" -> "<0.32552.4>" [ label = "{fill,1,1}" ] ;
|
||||
"<0.32552.4>" -> "<0.32555.4>" [ label = "error_trimmed" ] ;
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "End read repair", textbgcolour="aqua"] ;
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "Our attempt to write LPN 1 has failed. Must ask sequencer for a new LPN.", textbgcolour="yellow"] ;
|
||||
"<0.32551.4>" abox "<0.32552.4>" [ label = "LPN 2 is written (race details omitted)", textbgcolour="orange"] ;
|
||||
"<0.32551.4>" abox "<0.32552.4>" [ label = "LPN 3 is written (race details omitted)", textbgcolour="orange"] ;
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "Sequencer assigns LPN 4", textbgcolour="yellow"] ;
|
||||
"<0.32555.4>" -> "<0.32551.4>" [ label = "{write,1,4,<<0>>}" ] ;
|
||||
"<0.32551.4>" -> "<0.32555.4>" [ label = "ok" ] ;
|
||||
"<0.32555.4>" -> "<0.32552.4>" [ label = "{write,1,4,<<0>>}" ] ;
|
||||
"<0.32552.4>" -> "<0.32555.4>" [ label = "ok" ] ;
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "append_page() -> LPN 4", textbgcolour="yellow"] ;
|
||||
"<0.32555.4>" abox "<0.32557.4>" [ label="Small problem: the PULSE model never believes that append_page ever wrote LPN 1", textcolour="red"];
|
||||
"<0.32556.4>" abox "<0.32556.4>" [ label = "read_page(LPN 1)", textbgcolour="yellow"] ;
|
||||
"<0.32556.4>" -> "<0.32552.4>" [ label = "{read,1,4}" ] ;
|
||||
"<0.32552.4>" -> "<0.32556.4>" [ label = "{ok,<<0>>}" ] ;
|
||||
"<0.32556.4>" abox "<0.32556.4>" [ label = "read_page(LPN 4) -> {ok, <<0>>}", textbgcolour="yellow"] ;
|
||||
"<0.32555.4>" abox "<0.32557.4>" [ label="Big problem: Client2 has witnessed the same page written at LPN 1 and at LPN 4.", textcolour="red"];
|
||||
"<0.32555.4>" abox "<0.32557.4>" [ label="", textcolour="red"];
|
||||
"<0.32555.4>" abox "<0.32557.4>" [ label="", textcolour="red"];
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
msc {
|
||||
"<0.32555.4>" [label="Client1"], "<0.32551.4>" [label="FLU1=Head"], "<0.32552.4>" [label="FLU2=Tail"], "<0.32556.4>" [label="Client2"], "<0.32557.4>" [label="Client3"];
|
||||
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "Writer", textbgcolour="orange"],
|
||||
"<0.32556.4>" abox "<0.32556.4>" [ label = "Reader", textbgcolour="orange"],
|
||||
"<0.32557.4>" abox "<0.32557.4>" [ label = "Trimmer", textbgcolour="orange"];
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "append_page()", textbgcolour="yellow"] ;
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "Sequencer assigns LPN 1", textbgcolour="yellow"] ;
|
||||
"<0.32555.4>" -> "<0.32551.4>" [ label = "{write,1,1,<<0>>}" ] ;
|
||||
"<0.32551.4>" -> "<0.32555.4>" [ label = "ok" ] ;
|
||||
"<0.32556.4>" abox "<0.32556.4>" [ label = "read_page(LPN 1)", textbgcolour="yellow"] ;
|
||||
"<0.32556.4>" -> "<0.32552.4>" [ label = "{read,1,1}" ] ;
|
||||
"<0.32552.4>" -> "<0.32556.4>" [ label = "error_unwritten" ] ;
|
||||
"<0.32556.4>" abox "<0.32556.4>" [ label = "Start read repair", textbgcolour="aqua"] ;
|
||||
"<0.32556.4>" -> "<0.32551.4>" [ label = "{read,1,1}" ] ;
|
||||
"<0.32551.4>" -> "<0.32556.4>" [ label = "{ok,<<0>>}" ] ;
|
||||
"<0.32556.4>" -> "<0.32552.4>" [ label = "{write,1,1,<<0>>}" ] ;
|
||||
"<0.32552.4>" -> "<0.32556.4>" [ label = "ok" ] ;
|
||||
"<0.32556.4>" abox "<0.32556.4>" [ label = "End read repair", textbgcolour="aqua"] ;
|
||||
"<0.32556.4>" abox "<0.32556.4>" [ label = "read_page(LPN 1) -> {ok, <<0>>}", textbgcolour="yellow"] ;
|
||||
"<0.32556.4>" abox "<0.32556.4>" [ label = "See red stuff at bottom....", textcolour="red"] ;
|
||||
# "<0.32556.4>" abox "<0.32556.4>" [ label = "But PULSE thinks that LPN 1 was never written.", textcolour="red"] ;
|
||||
# "<0.32556.4>" abox "<0.32556.4>" [ label = "Fixing this requires ... lots of pondering...", textcolour="red"] ;
|
||||
"<0.32557.4>" -> "<0.32551.4>" [ label = "{trim,1,1}" ] ;
|
||||
"<0.32551.4>" -> "<0.32557.4>" [ label = "ok" ] ;
|
||||
"<0.32557.4>" -> "<0.32552.4>" [ label = "{trim,1,1}" ] ;
|
||||
"<0.32552.4>" -> "<0.32557.4>" [ label = "ok" ] ;
|
||||
"<0.32555.4>" -> "<0.32552.4>" [ label = "{write,1,1,<<0>>}" ] ;
|
||||
"<0.32552.4>" -> "<0.32555.4>" [ label = "error_overwritten", textbgcolour="silver" ] ;
|
||||
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "Our attempt to write LPN 1 is interrupted", textbgcolour="yellow"] ;
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "Check if an eager read-repair has written our data for us.", textbgcolour="yellow"] ;
|
||||
"<0.32555.4>" -> "<0.32552.4>" [ label = "{read,1,1}" ] ;
|
||||
"<0.32552.4>" -> "<0.32555.4>" [ label = "error_trimmed" ] ;
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "Wow, an eager trimmer got us, ouch.", textbgcolour="yellow"] ;
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "Start read repair", textbgcolour="aqua"] ;
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "Read repair here is for sanity checking, not really necessary.", textbgcolour="yellow"] ;
|
||||
"<0.32555.4>" -> "<0.32551.4>" [ label = "{read,1,1}" ] ;
|
||||
"<0.32551.4>" -> "<0.32555.4>" [ label = "error_trimmed" ] ;
|
||||
"<0.32555.4>" -> "<0.32552.4>" [ label = "{fill,1,1}" ] ;
|
||||
"<0.32552.4>" -> "<0.32555.4>" [ label = "error_trimmed" ] ;
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "End read repair", textbgcolour="aqua"] ;
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "Our attempt to write LPN 1 has failed. Must ask sequencer for a new LPN.", textbgcolour="yellow"] ;
|
||||
"<0.32551.4>" abox "<0.32552.4>" [ label = "LPN 2 and 3 are written (race details omitted)", textbgcolour="orange"] ;
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "Sequencer assigns LPN 4", textbgcolour="yellow"] ;
|
||||
"<0.32555.4>" -> "<0.32551.4>" [ label = "{write,1,4,<<0>>}" ] ;
|
||||
"<0.32551.4>" -> "<0.32555.4>" [ label = "ok" ] ;
|
||||
"<0.32555.4>" -> "<0.32552.4>" [ label = "{write,1,4,<<0>>}" ] ;
|
||||
"<0.32552.4>" -> "<0.32555.4>" [ label = "ok" ] ;
|
||||
"<0.32555.4>" abox "<0.32555.4>" [ label = "append_page() -> LPN 4", textbgcolour="yellow"] ;
|
||||
"<0.32555.4>" abox "<0.32557.4>" [ label="Small problem: the PULSE model never believes that append_page ever wrote LPN 1", textcolour="red"];
|
||||
"<0.32556.4>" abox "<0.32556.4>" [ label = "read_page(LPN 1)", textbgcolour="yellow"] ;
|
||||
"<0.32556.4>" -> "<0.32552.4>" [ label = "{read,1,4}" ] ;
|
||||
"<0.32552.4>" -> "<0.32556.4>" [ label = "{ok,<<0>>}" ] ;
|
||||
"<0.32556.4>" abox "<0.32556.4>" [ label = "read_page(LPN 4) -> {ok, <<0>>}", textbgcolour="yellow"] ;
|
||||
"<0.32555.4>" abox "<0.32557.4>" [ label="Big problem: Client2 has witnessed the same page written at LPN 1 and at LPN 4.", textcolour="red"];
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
msc {
|
||||
client1, FLU1, FLU2, client2, client3;
|
||||
|
||||
client1 -> FLU1 [label="{write,epoch1,<<Not unique page>>}"];
|
||||
client1 <- FLU1 [label="ok"];
|
||||
|
||||
client3 -> FLU2 [label="{seal,epoch1}"];
|
||||
client3 <- FLU2 [label="{ok,...}"];
|
||||
client3 -> FLU1 [label="{seal,epoch1}"];
|
||||
client3 <- FLU1 [label="{ok,...}"];
|
||||
|
||||
client2 -> FLU1 [label="{write,epoch1,<<Not unique page>>}"];
|
||||
client2 <- FLU1 [label="error_epoch"];
|
||||
client2 abox client2 [label="Ok, get the new epoch info....", textbgcolour="silver"];
|
||||
client2 -> FLU1 [label="{write,epoch2,<<Not unique page>>}"];
|
||||
client2 <- FLU1 [label="error_overwritten"];
|
||||
|
||||
client1 -> FLU2 [label="{write,epoch1,<<Not unique page>>}"];
|
||||
client1 <- FLU2 [label="error_epoch"];
|
||||
client1 abox client1 [label="Ok, hrm.", textbgcolour="silver"];
|
||||
|
||||
client3 abox client3 [ label = "Start read repair", textbgcolour="aqua"] ;
|
||||
client3 -> FLU1 [label="{read,epoch2}"];
|
||||
client3 <- FLU1 [label="{ok,<<Not unique page>>}"];
|
||||
client3 -> FLU2 [label="{write,epoch2,<<Not unique page>>}"];
|
||||
client3 <- FLU2 [label="ok"];
|
||||
client3 abox client3 [ label = "End read repair", textbgcolour="aqua"] ;
|
||||
client3 abox client3 [ label = "We saw <<Not unique page>>", textbgcolour="silver"] ;
|
||||
|
||||
client1 -> FLU2 [label="{write,epoch2,<<Not unique page>>}"];
|
||||
client1 <- FLU2 [label="error_overwritten"];
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,109 +0,0 @@
|
|||
digraph {
|
||||
compound=true
|
||||
label="Machi chain management flowchart (sample)";
|
||||
|
||||
node[shape="box", style="rounded"]
|
||||
start;
|
||||
node[shape="box", style="rounded", label="stop1"]
|
||||
stop1;
|
||||
node[shape="box", style="rounded", label="stop2"]
|
||||
stop2;
|
||||
node[shape="box", style="rounded"]
|
||||
crash;
|
||||
|
||||
subgraph clustera {
|
||||
node[shape="parallelogram", style="", label="Set retry counter = 0"]
|
||||
a05_retry;
|
||||
node[shape="parallelogram", style="", label="Create P_newprop @ epoch E+1\nbased on P_current @ epoch E"]
|
||||
a10_create;
|
||||
node[shape="parallelogram", style="", label="Get latest public projection, P_latest"]
|
||||
a20_get;
|
||||
node[shape="diamond", style="", label="Epoch(P_latest) > Epoch(P_current)\norelse\nP_latest was not unanimous"]
|
||||
a30_epoch;
|
||||
node[shape="diamond", style="", label="Epoch(P_latest) == Epoch(P_current)"]
|
||||
a40_epochequal;
|
||||
node[shape="diamond", style="", label="P_latest == P_current"]
|
||||
a50_equal;
|
||||
}
|
||||
|
||||
subgraph clustera100 {
|
||||
node[shape="diamond", style="", label="Write P_newprop to everyone"]
|
||||
a100_write;
|
||||
}
|
||||
|
||||
subgraph clusterb {
|
||||
node[shape="diamond", style="", label="P_latest was unanimous?"]
|
||||
b10_unanimous;
|
||||
node[shape="diamond", style="", label="Retry counter too big?"]
|
||||
b20_counter;
|
||||
node[shape="diamond", style="", label="Rank(P_latest) >= Rank(P_newprop)"]
|
||||
b30_rank;
|
||||
node[shape="diamond", style="", label="P_latest.upi == P_newprop.upi\nand also\nPlatest.repairing == P_newprop.repairing"]
|
||||
b40_condc;
|
||||
node[shape="square", style="", label="P_latest author is\ntoo slow, let's try!"]
|
||||
b45_lets;
|
||||
node[shape="parallelogram", style="", label="P_newprop is better than P_latest.\nSet P_newprop.epoch = P_latest.epoch + 1."]
|
||||
b50_better;
|
||||
}
|
||||
|
||||
subgraph clusterc {
|
||||
node[shape="diamond", style="", label="Is Move(P_current, P_latest) ok?"]
|
||||
c10_move;
|
||||
node[shape="parallelogram", style="", label="Tell Author(P_latest) to rewrite\nwith a bigger epoch number"]
|
||||
c20_tell;
|
||||
}
|
||||
|
||||
subgraph clusterd {
|
||||
node[shape="diamond", style="", label="Use P_latest as the\nnew P_current"]
|
||||
d10_use;
|
||||
}
|
||||
|
||||
start -> a05_retry;
|
||||
|
||||
a05_retry -> a10_create;
|
||||
a10_create -> a20_get;
|
||||
a20_get -> a30_epoch;
|
||||
a30_epoch -> a40_epochequal[label="false"];
|
||||
a30_epoch -> b10_unanimous[label="true"];
|
||||
a40_epochequal -> a50_equal[label="true"];
|
||||
a40_epochequal -> crash[label="falseXX"];
|
||||
a50_equal -> stop1[label="true"];
|
||||
a50_equal -> b20_counter[label="false"];
|
||||
|
||||
a100_write -> a10_create;
|
||||
|
||||
b10_unanimous -> c10_move[label="yes"];
|
||||
b10_unanimous -> b20_counter[label="no"];
|
||||
b20_counter -> b45_lets[label="true"];
|
||||
b20_counter -> b30_rank[label="false"];
|
||||
b30_rank -> b40_condc[label="false"];
|
||||
b30_rank -> c20_tell[label="true"];
|
||||
b40_condc -> b50_better[label="false"];
|
||||
b40_condc -> c20_tell[label="true"];
|
||||
b45_lets -> b50_better;
|
||||
b50_better -> a100_write;
|
||||
|
||||
c10_move -> d10_use[label="yes"];
|
||||
c10_move -> a100_write[label="no"];
|
||||
c20_tell -> b50_better;
|
||||
|
||||
d10_use -> stop2;
|
||||
|
||||
{rank=same; clustera clusterb clusterc clusterd};
|
||||
|
||||
// {rank=same; a10_create b10_unanimous c10_move d10_use stop2};
|
||||
// {rank=same; a20_get b20_counter c20_tell};
|
||||
// {rank=same; a30_epoch b40_condc};
|
||||
// {rank=same; a40_epochequal b40_condc crash};
|
||||
// {rank=same; stop1 a50_equal b50_better};
|
||||
|
||||
// if_valid;
|
||||
//
|
||||
// start -> input;
|
||||
// input -> if_valid;
|
||||
// if_valid -> message[label="no"];
|
||||
// if_valid -> end[label="yes"];
|
||||
// message -> input;
|
||||
|
||||
// {rank=same; message input}
|
||||
}
|
6
prototype/chain-manager/rebar.config
Normal file
6
prototype/chain-manager/rebar.config
Normal file
|
@ -0,0 +1,6 @@
|
|||
%%% {erl_opts, [warnings_as_errors, {parse_transform, lager_transform}, debug_info]}.
|
||||
{erl_opts, [{parse_transform, lager_transform}, debug_info]}.
|
||||
{deps, [
|
||||
{lager, "2.0.1", {git, "git://github.com/basho/lager.git", {tag, "2.0.1"}}}
|
||||
]}.
|
||||
|
9
prototype/chain-manager/src/foo.app.src
Normal file
9
prototype/chain-manager/src/foo.app.src
Normal file
|
@ -0,0 +1,9 @@
|
|||
{application, foo, [
|
||||
{description, "Prototype of Machi chain manager."},
|
||||
{vsn, "0.0.0"},
|
||||
{applications, [kernel, stdlib, lager]},
|
||||
{mod,{foo_unfinished_app,[]}},
|
||||
{registered, []},
|
||||
{env, [
|
||||
]}
|
||||
]}.
|
Loading…
Reference in a new issue