removing tabs from MSV examples

This commit is contained in:
Kenneth McMillan 2017-06-10 15:22:13 -07:00
Родитель 08a581a019
Коммит b6ff8f1e26
30 изменённых файлов: 1045 добавлений и 1075 удалений

Просмотреть файл

@ -13,10 +13,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hello4", "hello4.vcxproj",
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5D1E04F7-4717-4DC2-976E-0F5CD418F4D3}.Debug|x64.ActiveCfg = Debug|x64

Просмотреть файл

@ -34,14 +34,14 @@ object spec = {
# This says to initialize `pending` to `false`.
after init {
pending := false
pending := false
}
# This says, before executing the implementation of `hello`, set
# `pending` to true.
before hello(val:t) {
pending := true
pending := true
}
# This says, before executing the implementation of `world`,
@ -49,8 +49,8 @@ object spec = {
# an unsolicited call to `world`, this assertion will fail.
before world(val:t) {
assert pending;
pending := false
assert pending;
pending := false
}
}
@ -59,7 +59,7 @@ object spec = {
object impl = {
implement hello {
call world(val+1)
call world(val+1)
}
}

Просмотреть файл

@ -28,18 +28,18 @@ object spec = {
var hello_value : t
after init {
pending := false
pending := false
}
before hello(val:t) {
pending := true;
hello_value := val # remember the value
pending := true;
hello_value := val # remember the value
}
before world(val:t) {
assert pending;
assert val > hello_value; # new assertion
pending := false
assert pending;
assert val > hello_value; # new assertion
pending := false
}
}
@ -47,7 +47,7 @@ object spec = {
object impl = {
implement hello {
call world(val+1)
call world(val+1)
}
}

Просмотреть файл

@ -27,19 +27,19 @@ object spec = {
var hello_value : t
after init {
pending := false
pending := false
}
before hello(val:t) {
assert val + 1 ~= 0; # val is not max
pending := true;
hello_value := val
assert val + 1 ~= 0; # val is not max
pending := true;
hello_value := val
}
before world(val:t) {
assert pending;
assert val > hello_value;
pending := false
assert pending;
assert val > hello_value;
pending := false
}
}
@ -52,7 +52,7 @@ object spec = {
object impl = {
implement hello {
call world(val+1)
call world(val+1)
}
}

Просмотреть файл

@ -26,21 +26,21 @@ object spec = {
var side : side_t
after init {
side := left
side := left
}
# When `ping` occurs, the ball must be on the left. It moves to the right.
before intf.ping {
assert side = left;
side := right
assert side = left;
side := right
}
# When `pong` occurs, the ball must be on the rightr. It moves to the left.
before intf.pong {
assert side = right;
side := left
assert side = right;
side := left
}
}
@ -55,14 +55,14 @@ object left_player = {
init ball
action hit = {
if ball {
call intf.ping;
ball := false
}
if ball {
call intf.ping;
ball := false
}
}
implement intf.pong {
ball := true
ball := true
}
}
@ -75,14 +75,14 @@ object right_player = {
init ~ball
action hit = {
if ball {
call intf.pong;
ball := false
}
if ball {
call intf.pong;
ball := false
}
}
implement intf.ping {
ball := true
ball := true
}
}

Просмотреть файл

@ -11,10 +11,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pingpong_bad", "pingpong_ba
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A48A9407-CA01-4B56-8D51-303F4FC5F6E1}.Debug|x64.ActiveCfg = Debug|x64

Просмотреть файл

@ -12,13 +12,13 @@ object spec = {
init side = left
before intf.ping {
assert side = left;
side := right
assert side = left;
side := right
}
before intf.pong {
assert side = right;
side := left
assert side = right;
side := left
}
}
@ -27,12 +27,12 @@ object left_player = {
init ball
action hit = {
call intf.ping; # forgot to test ball!
ball := false
call intf.ping; # forgot to test ball!
ball := false
}
implement intf.pong {
ball := true
ball := true
}
conjecture left_player.ball -> spec.side = left
@ -43,14 +43,14 @@ object right_player = {
init ~ball
action hit = {
if ball {
call intf.pong;
ball := false
}
if ball {
call intf.pong;
ball := false
}
}
implement intf.ping {
ball := true
ball := true
}
conjecture right_player.ball -> spec.side = right

Просмотреть файл

@ -22,19 +22,19 @@ object spec = {
var side : side_t
after init {
side := left
side := left
}
before intf.ping {
assert side = left & ...;
side := right
assert side = left & ...;
side := right
}
# When `pong` occurs, the ball must be on the rightr. It moves to the left.
before intf.pong {
assert side = right & ...;
side := left
assert side = right & ...;
side := left
}
}
@ -47,15 +47,15 @@ object left_player = {
...
action hit = {
if ball {
call intf.ping(...);
ball := false
}
if ball {
call intf.ping(...);
ball := false
}
}
implement intf.pong(val:t) {
ball := true;
...
ball := true;
...
}
}
@ -67,15 +67,15 @@ object right_player = {
...
action hit = {
if ball {
call intf.pong(...);
ball := false
}
if ball {
call intf.pong(...);
ball := false
}
}
implement intf.ping(val:t) {
ball := true;
...
ball := true;
...
}
}

Просмотреть файл

@ -9,10 +9,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pingpong_ex_right", "pingpo
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A48A9407-CA01-4B56-8D51-303F4FC5F6E1}.Debug|x64.ActiveCfg = Debug|x64

Просмотреть файл

@ -22,19 +22,19 @@ object spec = {
var side : side_t
after init {
side := left
side := left
}
before intf.ping {
assert side = left & (val/2)*2 = val;
side := right
assert side = left & (val/2)*2 = val;
side := right
}
# When `pong` occurs, the ball must be on the rightr. It moves to the left.
before intf.pong {
assert side = right & (val/2)*2+1 = val;
side := left
assert side = right & (val/2)*2+1 = val;
side := left
}
}
@ -46,19 +46,19 @@ object left_player = {
init ball
var next : t
after init {
next := 0;
next := 0;
}
action hit = {
if ball {
call intf.ping(next);
ball := false
}
if ball {
call intf.ping(next);
ball := false
}
}
implement intf.pong(val:t) {
ball := true;
next := val + 1;
ball := true;
next := val + 1;
}
}
@ -70,15 +70,15 @@ object right_player = {
var next : t
action hit = {
if ball {
call intf.pong(next);
ball := false
}
if ball {
call intf.pong(next);
ball := false
}
}
implement intf.ping(val:t) {
ball := true;
next := val + 1;
ball := true;
next := val + 1;
}
}

Просмотреть файл

@ -13,19 +13,19 @@ module message_queue(net_msg,seq_num) = {
instance imap : ordered_map_impl(seq_num,net_msg.t)
implement enqueue {
call imap.set(net_msg.num(msg),msg)
call imap.set(net_msg.num(msg),msg)
}
implement empty {
res := seq_num.iter.is_end(imap.lub(seq_num.iter.create(0)))
res := seq_num.iter.is_end(imap.lub(seq_num.iter.create(0)))
}
implement delete_all(seq:seq_num.t) {
call imap.erase(seq_num.iter.create(0),seq_num.iter.create(seq_num.next(seq)))
call imap.erase(seq_num.iter.create(0),seq_num.iter.create(seq_num.next(seq)))
}
implement pick_one {
res := imap.get(seq_num.iter.val(imap.lub(seq_num.iter.create(0))),res)
res := imap.get(seq_num.iter.val(imap.lub(seq_num.iter.create(0))),res)
}
}

Просмотреть файл

@ -60,9 +60,9 @@ type request_kind = {write,read}
object request_body = {
type t = struct {
knd : request_kind,
ky : key,
vl : value
knd : request_kind,
ky : key,
vl : value
}
}
@ -72,8 +72,8 @@ object request_body = {
object request = {
type t = struct {
tx : txid,
bd : request_body.t
tx : txid,
bd : request_body.t
}
}
@ -83,7 +83,7 @@ object request = {
object response_body = {
type t = struct {
vl : value
vl : value
}
}
@ -92,8 +92,8 @@ object response_body = {
object response = {
type t = struct {
tx : txid,
bd : response_body.t
tx : txid,
bd : response_body.t
}
}
@ -107,15 +107,15 @@ object response = {
module replica = {
function store(K:key) : value
after init {
store(K) := 0
store(K) := 0
}
action exec(inp : request_body.t) returns (out:response_body.t) = {
if inp.knd = write {
store(inp.ky) := inp.vl;
}
else if inp.knd = read {
out.vl := store(inp.ky);
}
if inp.knd = write {
store(inp.ky) := inp.vl;
}
else if inp.knd = read {
out.vl := store(inp.ky);
}
}
}
@ -164,17 +164,17 @@ object ref = {
relation committed(X:txid)
after init {
next := 0;
committed(X) := false;
next := 0;
committed(X) := false;
}
# The create action simply generates a new transaction id and stores
# the request.
implement create {
tx := next;
txs(tx) := inp;
next := next + 1;
tx := next;
txs(tx) := inp;
next := next + 1;
}
# The commit action asserts that the transaction id must be for an
@ -184,10 +184,10 @@ object ref = {
# that the assertions are guarantees for the caller.
implement commit {
assert 0 <= tx & tx < next;
assert ~committed(tx);
txres(tx) := rep.exec(txs(tx));
committed(tx) := true;
assert 0 <= tx & tx < next;
assert ~committed(tx);
txres(tx) := rep.exec(txs(tx));
committed(tx) := true;
}
delegate commit
@ -195,8 +195,8 @@ object ref = {
# be committed, then returns the stored result.
implement eval {
assert committed(tx);
res := txres(tx);
assert committed(tx);
res := txres(tx);
}
delegate eval
@ -250,11 +250,11 @@ module client(cid,srvr_chan,cl_chans) = {
# server.
implement client_request {
var m : req_msg;
m.cid := cid;
m.req.tx := ref.create(req,dst);
m.req.bd := req;
call srvr_chan.send(m);
var m : req_msg;
m.cid := cid;
m.req.tx := ref.create(req,dst);
m.req.bd := req;
call srvr_chan.send(m);
}
# To handle a response from the server, we simply pass it to the
@ -262,7 +262,7 @@ module client(cid,srvr_chan,cl_chans) = {
# "ghost" and is only used for specification.
implement cl_chans.recv(resp : response.t) {
call client_response(resp.bd,resp.tx)
call client_response(resp.bd,resp.tx)
}
}
@ -276,7 +276,7 @@ module server_node(port, cl_chans) = {
instance rep : replica
instance req_chan : nondup_endpoint(port,req_msg)
# When we receive a request message on our port, we first commit the
# transaction id, then build a response message by executing the
# trasnaction on the replica, then send the response to the client. In
@ -289,12 +289,12 @@ module server_node(port, cl_chans) = {
# verification.
implement req_chan.recv(inp : req_msg) {
call ref.commit(inp.req.tx,dest.srvr);
var rr := inp.req.bd;
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res)
call ref.commit(inp.req.tx,dest.srvr);
var rr := inp.req.bd;
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res)
}
}
@ -334,13 +334,13 @@ object service_spec = {
relation responded(X:txid)
after init {
responded(X) := false;
responded(X) := false;
}
before cl_chans.send(p : client_id, m : response.t) {
assert ~responded(m.tx);
assert m.bd = ref.eval(m.tx);
responded(m.tx) := true;
assert ~responded(m.tx);
assert m.bd = ref.eval(m.tx);
responded(m.tx) := true;
}
}

Просмотреть файл

@ -7,10 +7,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "repstore1_srvr", "repstore1
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A48A9407-CA01-4B56-8D51-303F4FC5F6E1}.Debug|x64.ActiveCfg = Debug|x64

Просмотреть файл

@ -68,29 +68,29 @@ type request_kind = {write,read}
object request_body = {
type t = struct {
knd : request_kind,
ky : key,
vl : value
knd : request_kind,
ky : key,
vl : value
}
}
object request = {
type t = struct {
tx : txid,
bd : request_body.t
tx : txid,
bd : request_body.t
}
}
object response_body = {
type t = struct {
vl : value
vl : value
}
}
object response = {
type t = struct {
tx : txid,
bd : response_body.t
tx : txid,
bd : response_body.t
}
}
@ -99,15 +99,15 @@ object response = {
module replica = {
function store(K:key) : value
after init {
store(K) := 0
store(K) := 0
}
action exec(inp : request_body.t) returns (out:response_body.t) = {
if inp.knd = write {
store(inp.ky) := inp.vl;
}
else if inp.knd = read {
out.vl := store(inp.ky);
}
if inp.knd = write {
store(inp.ky) := inp.vl;
}
else if inp.knd = read {
out.vl := store(inp.ky);
}
}
}
@ -137,27 +137,27 @@ object ref = {
relation committed(X:txid)
after init {
next := 0;
committed(X) := false;
next := 0;
committed(X) := false;
}
implement create {
tx := next;
txs(tx) := inp;
next := next + 1;
tx := next;
txs(tx) := inp;
next := next + 1;
}
implement commit {
assert 0 <= tx & tx < next;
assert ~committed(tx);
txres(tx) := rep.exec(txs(tx));
committed(tx) := true;
assert 0 <= tx & tx < next;
assert ~committed(tx);
txres(tx) := rep.exec(txs(tx));
committed(tx) := true;
}
delegate commit
implement eval {
assert committed(tx);
res := txres(tx);
assert committed(tx);
res := txres(tx);
}
delegate eval
@ -181,7 +181,7 @@ object ser = {
relation serialized(X:txid)
after init {
serialized(X) := false;
serialized(X) := false;
}
# The serializer also keeps track of the order serialization in a
@ -194,11 +194,11 @@ object ser = {
# only serialize write transactions.
implement serialize {
assert 0 <= tx & tx < ref.next;
assert ~serialized(tx);
assert ref.txs(tx).knd = write;
serialized(tx) := true;
call queue.push(tx);
assert 0 <= tx & tx < ref.next;
assert ~serialized(tx);
assert ref.txs(tx).knd = write;
serialized(tx) := true;
call queue.push(tx);
}
delegate serialize
@ -206,9 +206,9 @@ object ser = {
# in the order in which they are serialized.
before ref.commit(tx : txid,dst:dest.t) {
if ref.txs(tx).knd = write {
assert tx = queue.pop
}
if ref.txs(tx).knd = write {
assert tx = queue.pop
}
}
}
@ -244,15 +244,15 @@ module client(cid,prim_chan,sec_chan,cl_chans) = {
# parameter `the_dst`.
implement client_request {
var m : req_msg;
m.cid := cid;
m.req.tx := ref.create(req,the_dst);
m.req.bd := req;
if the_dst = dest.prim {
call prim_chan.send(m);
} else {
call sec_chan.send(m);
}
var m : req_msg;
m.cid := cid;
m.req.tx := ref.create(req,the_dst);
m.req.bd := req;
if the_dst = dest.prim {
call prim_chan.send(m);
} else {
call sec_chan.send(m);
}
}
# To handle a response from the server, we simply pass it to the
@ -260,7 +260,7 @@ module client(cid,prim_chan,sec_chan,cl_chans) = {
# "ghost" and is only used for specification.
implement cl_chans.recv(resp : response.t) {
call client_response(resp.bd,resp.tx)
call client_response(resp.bd,resp.tx)
}
}
@ -284,9 +284,9 @@ module primary_node(port, fwd_chan, rev_chan, cl_chans) = {
# Initially, all the counters are zero.
after init {
pending(K) := 0;
pending(K) := 0;
}
# When receiving a request message from a client, the primary
# node must first check whether it is a read or a write. In the case
# of a read, we check if the key has a pending write. If not, we commit
@ -297,33 +297,33 @@ module primary_node(port, fwd_chan, rev_chan, cl_chans) = {
#
implement req_chan.recv(inp : req_msg) {
var rr := inp.req.bd;
var rr := inp.req.bd;
if rr.knd = read {
if pending(rr.ky) = 0 {
call ref.commit(inp.req.tx,dest.prim);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res)
} else {
if pending(rr.ky) = 0 {
call ref.commit(inp.req.tx,dest.prim);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res)
} else {
call req_chan.send(inp); # if cannot execute, recirculate
}
} else if rr.knd = write {
call ser.serialize(inp.req.tx); # this is ghost!
call fwd_chan.send(inp);
pending(rr.ky) := pending(rr.ky).next;
var res := rep.exec(inp.req.bd);
}
}
} else if rr.knd = write {
call ser.serialize(inp.req.tx); # this is ghost!
call fwd_chan.send(inp);
pending(rr.ky) := pending(rr.ky).next;
var res := rep.exec(inp.req.bd);
}
}
# When we receive a write request on the acknowledgement channel,
# we decrement the pending count of the key.
implement rev_chan.recv(inp : req_msg) {
var rr := inp.req.bd;
if rr.knd = write {
pending(rr.ky) := pending(rr.ky).prev;
}
var rr := inp.req.bd;
if rr.knd = write {
pending(rr.ky) := pending(rr.ky).prev;
}
}
}
@ -337,17 +337,17 @@ module secondary_node(port, fwd_chan, rev_chan, cl_chans) = {
instance rep : replica
instance req_chan : nondup_endpoint(port,req_msg)
implement req_chan.recv(inp : req_msg) {
var rr := inp.req.bd;
var rr := inp.req.bd;
if rr.knd = read {
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call ref.commit(inp.req.tx,dest.sec);
call cl_chans(inp.cid).send(res);
}
# ignore writes!
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call ref.commit(inp.req.tx,dest.sec);
call cl_chans(inp.cid).send(res);
}
# ignore writes!
}
# When the secondary receives a forwarded write from the primary,
@ -356,12 +356,12 @@ module secondary_node(port, fwd_chan, rev_chan, cl_chans) = {
#
implement fwd_chan.recv(inp : req_msg) {
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(inp.req.bd);
call ref.commit(inp.req.tx,dest.sec);
call cl_chans(inp.cid).send(res);
call rev_chan.send(inp);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(inp.req.bd);
call ref.commit(inp.req.tx,dest.sec);
call cl_chans(inp.cid).send(res);
call rev_chan.send(inp);
}
}
@ -406,13 +406,13 @@ object service_spec = {
relation responded(X:txid)
after init {
responded(X) := false;
responded(X) := false;
}
before cl_chans.send(p : client_id, m : response.t) {
assert ~responded(m.tx);
assert m.bd = ref.eval(m.tx);
responded(m.tx) := true;
assert ~responded(m.tx);
assert m.bd = ref.eval(m.tx);
responded(m.tx) := true;
}
}
@ -427,7 +427,7 @@ object mid_spec = {
instance queue : unbounded_queue(txid)
after ser.serialize(tx:txid) {
call queue.push(tx);
call queue.push(tx);
}
# When a message is received at the secondary on the forward
@ -437,8 +437,8 @@ object mid_spec = {
# serialization order).
before fwd_chan.rcvr.recv(inp : req_msg) {
assert inp.req.bd = ref.txs(inp.req.tx);
assert inp.req.tx = queue.pop;
assert inp.req.bd = ref.txs(inp.req.tx);
assert inp.req.tx = queue.pop;
}
# This tells IVy that the above specification is a guarantee for
@ -458,7 +458,7 @@ object mid_spec = {
relation acked(X:txid)
after init {
acked(X) := false;
acked(X) := false;
}
# When an ack message is sent on the reverse channel, it must have
@ -467,10 +467,10 @@ object mid_spec = {
# fact that it is now acked.
before rev_chan.sndr.send(inp : req_msg) {
assert ref.committed(inp.req.tx);
assert ref.txs(inp.req.tx) = inp.req.bd;
assert ~acked(inp.req.tx);
acked(inp.req.tx) := true;
assert ref.committed(inp.req.tx);
assert ref.txs(inp.req.tx) = inp.req.bd;
assert ~acked(inp.req.tx);
acked(inp.req.tx) := true;
}
# When a request is created, we record the destination server. In
@ -483,16 +483,16 @@ object mid_spec = {
function req_dest(X:txid) : dest.t
after ref.create(inp : request_body.t, dst:dest.t) returns (tx : txid) {
req_dest(tx) := dst
req_dest(tx) := dst
}
# We now specify that all reads must be commited by the server
# they are addressed to, while all writes are committed by the
# secondary
before ref.commit(tx : txid,dst:dest.t) {
assert ref.txs(tx).knd = read -> req_dest(tx) = dst;
assert ref.txs(tx).knd = write -> dst = dest.sec
assert ref.txs(tx).knd = read -> req_dest(tx) = dst;
assert ref.txs(tx).knd = write -> dst = dest.sec
}
}

Просмотреть файл

@ -9,10 +9,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "repstore2_sec", "repstore2_
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A48A9407-CA01-4B56-8D51-303F4FC5F6E1}.Debug|x64.ActiveCfg = Debug|x64

Просмотреть файл

@ -39,29 +39,29 @@ type request_kind = {write,read}
object request_body = {
type t = struct {
knd : request_kind,
ky : key,
vl : value
knd : request_kind,
ky : key,
vl : value
}
}
object request = {
type t = struct {
tx : txid,
bd : request_body.t
tx : txid,
bd : request_body.t
}
}
object response_body = {
type t = struct {
vl : value
vl : value
}
}
object response = {
type t = struct {
tx : txid,
bd : response_body.t
tx : txid,
bd : response_body.t
}
}
@ -70,15 +70,15 @@ object response = {
module replica = {
function store(K:key) : value
after init {
store(K) := 0
store(K) := 0
}
action exec(inp : request_body.t) returns (out:response_body.t) = {
if inp.knd = write {
store(inp.ky) := inp.vl;
}
else if inp.knd = read {
out.vl := store(inp.ky);
}
if inp.knd = write {
store(inp.ky) := inp.vl;
}
else if inp.knd = read {
out.vl := store(inp.ky);
}
}
}
@ -108,27 +108,27 @@ object ref = {
relation committed(X:txid)
after init {
next := 0;
committed(X) := false;
next := 0;
committed(X) := false;
}
implement create {
tx := next;
txs(tx) := inp;
next := next + 1;
tx := next;
txs(tx) := inp;
next := next + 1;
}
implement commit {
assert 0 <= tx & tx < next;
assert ~committed(tx);
txres(tx) := rep.exec(txs(tx));
committed(tx) := true;
assert 0 <= tx & tx < next;
assert ~committed(tx);
txres(tx) := rep.exec(txs(tx));
committed(tx) := true;
}
delegate commit
implement eval {
assert committed(tx);
res := txres(tx);
assert committed(tx);
res := txres(tx);
}
delegate eval
@ -152,7 +152,7 @@ object ser = {
relation serialized(X:txid)
after init {
serialized(X) := false;
serialized(X) := false;
}
# To serialzie a write, we must guarantee that transaction exists,
@ -160,10 +160,10 @@ object ser = {
# only serialize write transactions.
implement serialize {
assert 0 <= tx & tx < ref.next;
assert ~serialized(tx);
assert ref.txs(tx).knd = write;
serialized(tx) := true;
assert 0 <= tx & tx < ref.next;
assert ~serialized(tx);
assert ref.txs(tx).knd = write;
serialized(tx) := true;
}
delegate serialize
@ -171,7 +171,7 @@ object ser = {
# until it is serialized.
before ref.commit(tx : txid,dst:dest.t) {
assert ref.txs(tx).knd = write -> serialized(tx);
assert ref.txs(tx).knd = write -> serialized(tx);
}
}
@ -212,15 +212,15 @@ module client(cid,prim_chan,sec_chan,cl_chans) = {
# parameter `the_dst`.
implement client_request {
var m : req_msg;
m.cid := cid;
m.req.tx := ref.create(req,the_dst);
m.req.bd := req;
if the_dst = dest.prim {
call prim_chan.send(m);
} else {
call sec_chan.send(m);
}
var m : req_msg;
m.cid := cid;
m.req.tx := ref.create(req,the_dst);
m.req.bd := req;
if the_dst = dest.prim {
call prim_chan.send(m);
} else {
call sec_chan.send(m);
}
}
# To handle a response from the server, we simply pass it to the
@ -228,7 +228,7 @@ module client(cid,prim_chan,sec_chan,cl_chans) = {
# "ghost" and is only used for specification.
implement cl_chans.recv(resp : response.t) {
call client_response(resp.bd,resp.tx)
call client_response(resp.bd,resp.tx)
}
}
@ -252,9 +252,9 @@ module primary_node(port, fwd_chan, rev_chan, cl_chans) = {
# Initially, all the counters are zero.
after init {
pending(K) := 0;
pending(K) := 0;
}
# When receiving a request message from a client, the primary
# node must first check whether it is a read or a write. In the case
# of a read, we check if the key has a pending write. If not, we commit
@ -265,32 +265,32 @@ module primary_node(port, fwd_chan, rev_chan, cl_chans) = {
#
implement req_chan.recv(inp : req_msg) {
var rr := inp.req.bd;
var rr := inp.req.bd;
if rr.knd = read {
if pending(rr.ky) = 0 {
call ref.commit(inp.req.tx,dest.prim);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res)
} else {
if pending(rr.ky) = 0 {
call ref.commit(inp.req.tx,dest.prim);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res)
} else {
call req_chan.send(inp); # if cannot execute, recirculate
}
} else if rr.knd = write {
call ser.serialize(inp.req.tx); # this is ghost!
call fwd_chan.send(inp);
var res := rep.exec(inp.req.bd);
}
}
} else if rr.knd = write {
call ser.serialize(inp.req.tx); # this is ghost!
call fwd_chan.send(inp);
var res := rep.exec(inp.req.bd);
}
}
# When we receive a write request on the acknowledgement channel,
# we decrement the pending count of the key.
implement rev_chan.recv(inp : req_msg) {
var rr := inp.req.bd;
if rr.knd = write {
pending(rr.ky) := pending(rr.ky).prev;
}
var rr := inp.req.bd;
if rr.knd = write {
pending(rr.ky) := pending(rr.ky).prev;
}
}
}
@ -304,16 +304,16 @@ module secondary_node(port, fwd_chan, rev_chan, cl_chans) = {
instance rep : replica
instance req_chan : nondup_endpoint(port,req_msg)
implement req_chan.recv(inp : req_msg) {
var rr := inp.req.bd;
var rr := inp.req.bd;
if rr.knd = read {
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res);
}
# ignore writes!
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res);
}
# ignore writes!
}
# When the secondary receives a forwarded write from the primary,
@ -322,11 +322,11 @@ module secondary_node(port, fwd_chan, rev_chan, cl_chans) = {
#
implement fwd_chan.recv(inp : req_msg) {
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(inp.req.bd);
call cl_chans(inp.cid).send(res);
call rev_chan.send(inp);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(inp.req.bd);
call cl_chans(inp.cid).send(res);
call rev_chan.send(inp);
}
}
@ -371,13 +371,13 @@ object service_spec = {
relation responded(X:txid)
after init {
responded(X) := false;
responded(X) := false;
}
before cl_chans.send(p : client_id, m : response.t) {
assert ~responded(m.tx);
assert m.bd = ref.eval(m.tx);
responded(m.tx) := true;
assert ~responded(m.tx);
assert m.bd = ref.eval(m.tx);
responded(m.tx) := true;
}
}
@ -392,7 +392,7 @@ object mid_spec = {
instance queue : unbounded_queue(txid)
after ser.serialize(tx:txid) {
call queue.push(tx);
call queue.push(tx);
}
# When a message is received at the secondary on the forward
@ -408,9 +408,9 @@ object mid_spec = {
# convenient.
before fwd_chan.rcvr.recv(inp : req_msg) {
assert inp.req.bd = ref.txs(inp.req.tx);
assert inp.req.tx = queue.pop;
call ref.commit(inp.req.tx,dest.sec);
assert inp.req.bd = ref.txs(inp.req.tx);
assert inp.req.tx = queue.pop;
call ref.commit(inp.req.tx,dest.sec);
}
# This tells IVy that the above specification is a guarantee for
@ -430,7 +430,7 @@ object mid_spec = {
relation acked(X:txid)
after init {
acked(X) := false;
acked(X) := false;
}
# When an ack message is sent on the reverse channel, must have
@ -439,10 +439,10 @@ object mid_spec = {
# record the fact that it is now acked.
before rev_chan.sndr.send(inp : req_msg) {
assert ref.txs(inp.req.tx) = inp.req.bd;
assert ref.committed(inp.req.tx);
assert ~acked(inp.req.tx);
acked(inp.req.tx) := true;
assert ref.txs(inp.req.tx) = inp.req.bd;
assert ref.committed(inp.req.tx);
assert ~acked(inp.req.tx);
acked(inp.req.tx) := true;
}
# When a request is created, we record the destination server. In
@ -455,24 +455,24 @@ object mid_spec = {
function req_dest(X:txid) : dest.t
after ref.create(inp : request_body.t, dst:dest.t) returns (tx : txid) {
req_dest(tx) := dst
req_dest(tx) := dst
}
# We now specify that all reads must be commited by the server
# they are addressed to, while all writes are committed by the
# secondary
before ref.commit(tx : txid,dst:dest.t) {
assert ref.txs(tx).knd = read -> req_dest(tx) = dst;
assert ref.txs(tx).knd = write -> dst = dest.sec
assert ref.txs(tx).knd = read -> req_dest(tx) = dst;
assert ref.txs(tx).knd = write -> dst = dest.sec
}
# Commit immediately all read requests from client to secondary
before sec.req_chan.recv(inp : req_msg) {
if inp.req.bd.knd = read {
call ref.commit(inp.req.tx,dest.sec)
}
if inp.req.bd.knd = read {
call ref.commit(inp.req.tx,dest.sec)
}
}
}

Просмотреть файл

@ -9,10 +9,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "repstore2bug_sec", "repstor
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A48A9407-CA01-4B56-8D51-303F4FC5F6E1}.Debug|x64.ActiveCfg = Debug|x64

Просмотреть файл

@ -44,29 +44,29 @@ type request_kind = {write,read}
object request_body = {
type t = struct {
knd : request_kind,
ky : key,
vl : value
knd : request_kind,
ky : key,
vl : value
}
}
object request = {
type t = struct {
tx : txid,
bd : request_body.t
tx : txid,
bd : request_body.t
}
}
object response_body = {
type t = struct {
vl : value
vl : value
}
}
object response = {
type t = struct {
tx : txid,
bd : response_body.t
tx : txid,
bd : response_body.t
}
}
@ -75,15 +75,15 @@ object response = {
module replica = {
function store(K:key) : value
after init {
store(K) := 0
store(K) := 0
}
action exec(inp : request_body.t) returns (out:response_body.t) = {
if inp.knd = write {
store(inp.ky) := inp.vl;
}
else if inp.knd = read {
out.vl := store(inp.ky);
}
if inp.knd = write {
store(inp.ky) := inp.vl;
}
else if inp.knd = read {
out.vl := store(inp.ky);
}
}
}
@ -113,27 +113,27 @@ object ref = {
relation committed(X:txid)
after init {
next := 0;
committed(X) := false;
next := 0;
committed(X) := false;
}
implement create {
tx := next;
txs(tx) := inp;
next := next + 1;
tx := next;
txs(tx) := inp;
next := next + 1;
}
implement commit {
assert 0 <= tx & tx < next;
assert ~committed(tx);
txres(tx) := rep.exec(txs(tx));
committed(tx) := true;
assert 0 <= tx & tx < next;
assert ~committed(tx);
txres(tx) := rep.exec(txs(tx));
committed(tx) := true;
}
delegate commit
implement eval {
assert committed(tx);
res := txres(tx);
assert committed(tx);
res := txres(tx);
}
delegate eval
@ -157,7 +157,7 @@ object ser = {
relation serialized(X:txid)
after init {
serialized(X) := false;
serialized(X) := false;
}
# To serialzie a write, we must guarantee that transaction exists,
@ -165,10 +165,10 @@ object ser = {
# only serialize write transactions.
implement serialize {
assert 0 <= tx & tx < ref.next;
assert ~serialized(tx);
assert ref.txs(tx).knd = write;
serialized(tx) := true;
assert 0 <= tx & tx < ref.next;
assert ~serialized(tx);
assert ref.txs(tx).knd = write;
serialized(tx) := true;
}
delegate serialize
@ -176,7 +176,7 @@ object ser = {
# until it is serialized.
before ref.commit(tx : txid,dst:dest.t) {
assert ref.txs(tx).knd = write -> serialized(tx);
assert ref.txs(tx).knd = write -> serialized(tx);
}
}
@ -217,15 +217,15 @@ module client(cid,prim_chan,sec_chan,cl_chans) = {
# parameter `the_dst`.
implement client_request {
var m : req_msg;
m.cid := cid;
m.req.tx := ref.create(req,the_dst);
m.req.bd := req;
if the_dst = dest.prim {
call prim_chan.send(m);
} else {
call sec_chan.send(m);
}
var m : req_msg;
m.cid := cid;
m.req.tx := ref.create(req,the_dst);
m.req.bd := req;
if the_dst = dest.prim {
call prim_chan.send(m);
} else {
call sec_chan.send(m);
}
}
# To handle a response from the server, we simply pass it to the
@ -233,7 +233,7 @@ module client(cid,prim_chan,sec_chan,cl_chans) = {
# "ghost" and is only used for specification.
implement cl_chans.recv(resp : response.t) {
call client_response(resp.bd,resp.tx)
call client_response(resp.bd,resp.tx)
}
}
@ -257,9 +257,9 @@ module primary_node(port, fwd_chan, rev_chan, cl_chans) = {
# Initially, all the counters are zero.
after init {
pending(K) := 0;
pending(K) := 0;
}
# When receiving a request message from a client, the primary
# node must first check whether it is a read or a write. In the case
# of a read, we check if the key has a pending write. If not, we commit
@ -270,33 +270,33 @@ module primary_node(port, fwd_chan, rev_chan, cl_chans) = {
#
implement req_chan.recv(inp : req_msg) {
var rr := inp.req.bd;
var rr := inp.req.bd;
if rr.knd = read {
if pending(rr.ky) = 0 {
call ref.commit(inp.req.tx,dest.prim);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res)
} else {
if pending(rr.ky) = 0 {
call ref.commit(inp.req.tx,dest.prim);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res)
} else {
call req_chan.send(inp); # if cannot execute, recirculate (HINT)
}
} else if rr.knd = write {
call ser.serialize(inp.req.tx); # this is ghost!
call fwd_chan.send(inp);
pending(rr.ky) := pending(rr.ky).next;
var res := rep.exec(inp.req.bd);
}
}
} else if rr.knd = write {
call ser.serialize(inp.req.tx); # this is ghost!
call fwd_chan.send(inp);
pending(rr.ky) := pending(rr.ky).next;
var res := rep.exec(inp.req.bd);
}
}
# When we receive a write request on the acknowledgement channel,
# we decrement the pending count of the key.
implement rev_chan.recv(inp : req_msg) {
var rr := inp.req.bd;
if rr.knd = write {
pending(rr.ky) := pending(rr.ky).prev;
}
var rr := inp.req.bd;
if rr.knd = write {
pending(rr.ky) := pending(rr.ky).prev;
}
}
}
@ -310,16 +310,16 @@ module secondary_node(port, fwd_chan, rev_chan, cl_chans) = {
instance rep : replica
instance req_chan : nondup_endpoint(port,req_msg)
implement req_chan.recv(inp : req_msg) {
var rr := inp.req.bd;
var rr := inp.req.bd;
if rr.knd = read {
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res);
}
# ignore writes!
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res);
}
# ignore writes!
}
# When the secondary receives a forwarded write from the primary,
@ -331,11 +331,11 @@ module secondary_node(port, fwd_chan, rev_chan, cl_chans) = {
# HINT: do something here (see req_chan.recv above)
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(inp.req.bd);
call cl_chans(inp.cid).send(res);
call rev_chan.send(inp);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(inp.req.bd);
call cl_chans(inp.cid).send(res);
call rev_chan.send(inp);
}
}
@ -380,13 +380,13 @@ object service_spec = {
relation responded(X:txid)
after init {
responded(X) := false;
responded(X) := false;
}
before cl_chans.send(p : client_id, m : response.t) {
assert ~responded(m.tx);
assert m.bd = ref.eval(m.tx);
responded(m.tx) := true;
assert ~responded(m.tx);
assert m.bd = ref.eval(m.tx);
responded(m.tx) := true;
}
}
@ -401,7 +401,7 @@ object mid_spec = {
instance queue : unbounded_queue(txid)
after ser.serialize(tx:txid) {
call queue.push(tx);
call queue.push(tx);
}
# When a message is received at the secondary on the forward
@ -417,9 +417,9 @@ object mid_spec = {
# convenient.
before fwd_chan.rcvr.recv(inp : req_msg) {
assert inp.req.bd = ref.txs(inp.req.tx);
assert inp.req.tx = queue.pop;
call ref.commit(inp.req.tx,dest.sec);
assert inp.req.bd = ref.txs(inp.req.tx);
assert inp.req.tx = queue.pop;
call ref.commit(inp.req.tx,dest.sec);
}
# This tells IVy that the above specification is a guarantee for
@ -439,7 +439,7 @@ object mid_spec = {
relation acked(X:txid)
after init {
acked(X) := false;
acked(X) := false;
}
# When an ack message is sent on the reverse channel, it must have
@ -448,10 +448,10 @@ object mid_spec = {
# fact that it is now acked.
before rev_chan.sndr.send(inp : req_msg) {
assert ref.committed(inp.req.tx);
assert ref.txs(inp.req.tx) = inp.req.bd;
assert ~acked(inp.req.tx);
acked(inp.req.tx) := true;
assert ref.committed(inp.req.tx);
assert ref.txs(inp.req.tx) = inp.req.bd;
assert ~acked(inp.req.tx);
acked(inp.req.tx) := true;
}
# When a request is created, we record the destination server. In
@ -467,24 +467,24 @@ object mid_spec = {
function req_dest(X:txid) : dest.t
after ref.create(inp : request_body.t, dst:dest.t) returns (tx : txid) {
req_dest(tx) := dst
req_dest(tx) := dst
}
# We now specify that all reads must be commited by the server
# they are addressed to, while all writes are committed by the
# secondary
before ref.commit(tx : txid,dst:dest.t) {
assert ref.txs(tx).knd = read -> req_dest(tx) = dst;
assert ref.txs(tx).knd = write -> dst = dest.sec
assert ref.txs(tx).knd = read -> req_dest(tx) = dst;
assert ref.txs(tx).knd = write -> dst = dest.sec
}
# Commit immediately all read requests from client to secondary
before sec.req_chan.recv(inp : req_msg) {
if inp.req.bd.knd = read {
call ref.commit(inp.req.tx,dest.sec)
}
if inp.req.bd.knd = read {
call ref.commit(inp.req.tx,dest.sec)
}
}
}

Просмотреть файл

@ -9,10 +9,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "repstore2ex_sec", "repstore
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A48A9407-CA01-4B56-8D51-303F4FC5F6E1}.Debug|x64.ActiveCfg = Debug|x64

Просмотреть файл

@ -44,29 +44,29 @@ type request_kind = {write,read}
object request_body = {
type t = struct {
knd : request_kind,
ky : key,
vl : value
knd : request_kind,
ky : key,
vl : value
}
}
object request = {
type t = struct {
tx : txid,
bd : request_body.t
tx : txid,
bd : request_body.t
}
}
object response_body = {
type t = struct {
vl : value
vl : value
}
}
object response = {
type t = struct {
tx : txid,
bd : response_body.t
tx : txid,
bd : response_body.t
}
}
@ -75,15 +75,15 @@ object response = {
module replica = {
function store(K:key) : value
after init {
store(K) := 0
store(K) := 0
}
action exec(inp : request_body.t) returns (out:response_body.t) = {
if inp.knd = write {
store(inp.ky) := inp.vl;
}
else if inp.knd = read {
out.vl := store(inp.ky);
}
if inp.knd = write {
store(inp.ky) := inp.vl;
}
else if inp.knd = read {
out.vl := store(inp.ky);
}
}
}
@ -113,27 +113,27 @@ object ref = {
relation committed(X:txid)
after init {
next := 0;
committed(X) := false;
next := 0;
committed(X) := false;
}
implement create {
tx := next;
txs(tx) := inp;
next := next + 1;
tx := next;
txs(tx) := inp;
next := next + 1;
}
implement commit {
assert 0 <= tx & tx < next;
assert ~committed(tx);
txres(tx) := rep.exec(txs(tx));
committed(tx) := true;
assert 0 <= tx & tx < next;
assert ~committed(tx);
txres(tx) := rep.exec(txs(tx));
committed(tx) := true;
}
delegate commit
implement eval {
assert committed(tx);
res := txres(tx);
assert committed(tx);
res := txres(tx);
}
delegate eval
@ -157,7 +157,7 @@ object ser = {
relation serialized(X:txid)
after init {
serialized(X) := false;
serialized(X) := false;
}
# To serialzie a write, we must guarantee that transaction exists,
@ -165,10 +165,10 @@ object ser = {
# only serialize write transactions.
implement serialize {
assert 0 <= tx & tx < ref.next;
assert ~serialized(tx);
assert ref.txs(tx).knd = write;
serialized(tx) := true;
assert 0 <= tx & tx < ref.next;
assert ~serialized(tx);
assert ref.txs(tx).knd = write;
serialized(tx) := true;
}
delegate serialize
@ -176,7 +176,7 @@ object ser = {
# until it is serialized.
before ref.commit(tx : txid,dst:dest.t) {
assert ref.txs(tx).knd = write -> serialized(tx);
assert ref.txs(tx).knd = write -> serialized(tx);
}
}
@ -217,15 +217,15 @@ module client(cid,prim_chan,sec_chan,cl_chans) = {
# parameter `the_dst`.
implement client_request {
var m : req_msg;
m.cid := cid;
m.req.tx := ref.create(req,the_dst);
m.req.bd := req;
if the_dst = dest.prim {
call prim_chan.send(m);
} else {
call sec_chan.send(m);
}
var m : req_msg;
m.cid := cid;
m.req.tx := ref.create(req,the_dst);
m.req.bd := req;
if the_dst = dest.prim {
call prim_chan.send(m);
} else {
call sec_chan.send(m);
}
}
# To handle a response from the server, we simply pass it to the
@ -233,7 +233,7 @@ module client(cid,prim_chan,sec_chan,cl_chans) = {
# "ghost" and is only used for specification.
implement cl_chans.recv(resp : response.t) {
call client_response(resp.bd,resp.tx)
call client_response(resp.bd,resp.tx)
}
}
@ -257,9 +257,9 @@ module primary_node(port, fwd_chan, rev_chan, cl_chans) = {
# Initially, all the counters are zero.
after init {
pending(K) := 0;
pending(K) := 0;
}
# When receiving a request message from a client, the primary
# node must first check whether it is a read or a write. In the case
# of a read, we check if the key has a pending write. If not, we commit
@ -270,36 +270,36 @@ module primary_node(port, fwd_chan, rev_chan, cl_chans) = {
#
implement req_chan.recv(inp : req_msg) {
var rr := inp.req.bd;
var rr := inp.req.bd;
if rr.knd = read {
if pending(rr.ky) = 0 {
call ref.commit(inp.req.tx,dest.prim);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res)
} else {
if pending(rr.ky) = 0 {
call ref.commit(inp.req.tx,dest.prim);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res)
} else {
# SOLN: if can't read, send on `fwd_chan`
# SOLN: if can't read, send on `fwd_chan`
call fwd_chan.send(inp);
}
} else if rr.knd = write {
call ser.serialize(inp.req.tx); # this is ghost!
call fwd_chan.send(inp);
pending(rr.ky) := pending(rr.ky).next;
var res := rep.exec(inp.req.bd);
}
}
} else if rr.knd = write {
call ser.serialize(inp.req.tx); # this is ghost!
call fwd_chan.send(inp);
pending(rr.ky) := pending(rr.ky).next;
var res := rep.exec(inp.req.bd);
}
}
# When we receive a write request on the acknowledgement channel,
# we decrement the pending count of the key.
implement rev_chan.recv(inp : req_msg) {
var rr := inp.req.bd;
if rr.knd = write {
pending(rr.ky) := pending(rr.ky).prev;
}
var rr := inp.req.bd;
if rr.knd = write {
pending(rr.ky) := pending(rr.ky).prev;
}
}
}
@ -313,16 +313,16 @@ module secondary_node(port, fwd_chan, rev_chan, cl_chans) = {
instance rep : replica
instance req_chan : nondup_endpoint(port,req_msg)
implement req_chan.recv(inp : req_msg) {
var rr := inp.req.bd;
var rr := inp.req.bd;
if rr.knd = read {
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res);
}
# ignore writes!
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res);
}
# ignore writes!
}
# When the secondary receives a forwarded write from the primary,
@ -334,20 +334,20 @@ module secondary_node(port, fwd_chan, rev_chan, cl_chans) = {
# SOLN: handle reads here just like above
var rr := inp.req.bd;
var rr := inp.req.bd;
if rr.knd = read {
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res);
}
else {
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(inp.req.bd);
call cl_chans(inp.cid).send(res);
call rev_chan.send(inp);
}
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res);
}
else {
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(inp.req.bd);
call cl_chans(inp.cid).send(res);
call rev_chan.send(inp);
}
}
}
@ -392,13 +392,13 @@ object service_spec = {
relation responded(X:txid)
after init {
responded(X) := false;
responded(X) := false;
}
before cl_chans.send(p : client_id, m : response.t) {
assert ~responded(m.tx);
assert m.bd = ref.eval(m.tx);
responded(m.tx) := true;
assert ~responded(m.tx);
assert m.bd = ref.eval(m.tx);
responded(m.tx) := true;
}
}
@ -413,7 +413,7 @@ object mid_spec = {
instance queue : unbounded_queue(txid)
after ser.serialize(tx:txid) {
call queue.push(tx);
call queue.push(tx);
}
# When a message is received at the secondary on the forward
@ -429,21 +429,21 @@ object mid_spec = {
# convenient.
before fwd_chan.rcvr.recv(inp : req_msg) {
assert inp.req.bd = ref.txs(inp.req.tx);
assert inp.req.bd = ref.txs(inp.req.tx);
# SOLN: before commiting a read from the forwarding channel,
# we need to change its destination. Else, the monitor for
# `ref.commit` below will fail. In case of writes, we do as before.
# SOLN: before commiting a read from the forwarding channel,
# we need to change its destination. Else, the monitor for
# `ref.commit` below will fail. In case of writes, we do as before.
if inp.req.bd.knd = read {
assert ~ref.committed(inp.req.tx);
assert req_dest(inp.req.tx) = dest.prim;
req_dest(inp.req.tx) := dest.sec
} else {
assert inp.req.tx = queue.pop;
};
if inp.req.bd.knd = read {
assert ~ref.committed(inp.req.tx);
assert req_dest(inp.req.tx) = dest.prim;
req_dest(inp.req.tx) := dest.sec
} else {
assert inp.req.tx = queue.pop;
};
call ref.commit(inp.req.tx,dest.sec);
call ref.commit(inp.req.tx,dest.sec);
}
# This tells IVy that the above specification is a guarantee for
@ -463,7 +463,7 @@ object mid_spec = {
relation acked(X:txid)
after init {
acked(X) := false;
acked(X) := false;
}
# When an ack message is sent on the reverse channel, it must have
@ -472,10 +472,10 @@ object mid_spec = {
# fact that it is now acked.
before rev_chan.sndr.send(inp : req_msg) {
assert ref.committed(inp.req.tx);
assert ref.txs(inp.req.tx) = inp.req.bd;
assert ~acked(inp.req.tx);
acked(inp.req.tx) := true;
assert ref.committed(inp.req.tx);
assert ref.txs(inp.req.tx) = inp.req.bd;
assert ~acked(inp.req.tx);
acked(inp.req.tx) := true;
}
# When a request is created, we record the destination server. In
@ -491,24 +491,24 @@ object mid_spec = {
function req_dest(X:txid) : dest.t
after ref.create(inp : request_body.t, dst:dest.t) returns (tx : txid) {
req_dest(tx) := dst
req_dest(tx) := dst
}
# We now specify that all reads must be commited by the server
# they are addressed to, while all writes are committed by the
# secondary
before ref.commit(tx : txid,dst:dest.t) {
assert ref.txs(tx).knd = read -> req_dest(tx) = dst;
assert ref.txs(tx).knd = write -> dst = dest.sec
assert ref.txs(tx).knd = read -> req_dest(tx) = dst;
assert ref.txs(tx).knd = write -> dst = dest.sec
}
# Commit immediately all read requests from client to secondary
before sec.req_chan.recv(inp : req_msg) {
if inp.req.bd.knd = read {
call ref.commit(inp.req.tx,dest.sec)
}
if inp.req.bd.knd = read {
call ref.commit(inp.req.tx,dest.sec)
}
}
}

Просмотреть файл

@ -9,10 +9,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "repstore2ex_soln_sec", "rep
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A48A9407-CA01-4B56-8D51-303F4FC5F6E1}.Debug|x64.ActiveCfg = Debug|x64

Просмотреть файл

@ -36,29 +36,29 @@ type request_kind = {write,read}
object request_body = {
type t = struct {
knd : request_kind,
ky : key,
vl : value
knd : request_kind,
ky : key,
vl : value
}
}
object request = {
type t = struct {
tx : txid,
bd : request_body.t
tx : txid,
bd : request_body.t
}
}
object response_body = {
type t = struct {
vl : value
vl : value
}
}
object response = {
type t = struct {
tx : txid,
bd : response_body.t
tx : txid,
bd : response_body.t
}
}
@ -67,15 +67,15 @@ object response = {
module replica = {
function store(K:key) : value
after init {
store(K) := 0
store(K) := 0
}
action exec(inp : request_body.t) returns (out:response_body.t) = {
if inp.knd = write {
store(inp.ky) := inp.vl;
}
else if inp.knd = read {
out.vl := store(inp.ky);
}
if inp.knd = write {
store(inp.ky) := inp.vl;
}
else if inp.knd = read {
out.vl := store(inp.ky);
}
}
}
@ -102,27 +102,27 @@ object ref = {
relation committed(X:txid)
after init {
next := 0;
committed(X) := false;
next := 0;
committed(X) := false;
}
implement create {
tx := next;
txs(tx) := inp;
next := next + 1;
tx := next;
txs(tx) := inp;
next := next + 1;
}
implement commit {
assert 0 <= tx & tx < next;
assert ~committed(tx);
txres(tx) := rep.exec(txs(tx));
committed(tx) := true;
assert 0 <= tx & tx < next;
assert ~committed(tx);
txres(tx) := rep.exec(txs(tx));
committed(tx) := true;
}
delegate commit
implement eval {
assert committed(tx);
res := txres(tx);
assert committed(tx);
res := txres(tx);
}
delegate eval
@ -142,7 +142,7 @@ object ser = {
relation serialized(X:txid)
after init {
serialized(X) := false;
serialized(X) := false;
}
# To serialzie a write, we must guarantee that transaction exists,
@ -150,10 +150,10 @@ object ser = {
# only serialize write transactions.
implement serialize {
assert 0 <= tx & tx < ref.next;
assert ~serialized(tx);
assert ref.txs(tx).knd = write;
serialized(tx) := true;
assert 0 <= tx & tx < ref.next;
assert ~serialized(tx);
assert ref.txs(tx).knd = write;
serialized(tx) := true;
}
delegate serialize
@ -161,7 +161,7 @@ object ser = {
# until it is serialized.
before ref.commit(tx : txid,dst:dest.t) {
assert ref.txs(tx).knd = write -> serialized(tx);
assert ref.txs(tx).knd = write -> serialized(tx);
}
}
@ -187,19 +187,19 @@ module client(cid,prim_chan,sec_chan,cl_chans) = {
action client_response(req : response_body.t, tx : txid)
implement client_request {
var m : req_msg;
m.cid := cid;
m.req.tx := ref.create(req,the_dst);
m.req.bd := req;
if the_dst = dest.prim {
call prim_chan.send(m);
} else {
call sec_chan.send(m);
}
var m : req_msg;
m.cid := cid;
m.req.tx := ref.create(req,the_dst);
m.req.bd := req;
if the_dst = dest.prim {
call prim_chan.send(m);
} else {
call sec_chan.send(m);
}
}
implement cl_chans.recv(resp : response.t) {
call client_response(resp.bd,resp.tx)
call client_response(resp.bd,resp.tx)
}
}
@ -222,14 +222,14 @@ module primary_node(port, fwd_chan, rev_chan, cl_chans) = {
var sec_failed : bool
after init {
pending(K) := 0;
sec_failed := false;
pending(K) := 0;
sec_failed := false;
}
# If we receive a failure message, set `sec_failed`.
implement fail_chan.recv(inp : fail_msg) {
sec_failed := true;
sec_failed := true;
}
@ -237,35 +237,35 @@ module primary_node(port, fwd_chan, rev_chan, cl_chans) = {
# and we no longer wait for acks.
implement req_chan.recv(inp : req_msg) {
var rr := inp.req.bd;
var rr := inp.req.bd;
if rr.knd = read {
if pending(rr.ky) = 0 | sec_failed {
call ref.commit(inp.req.tx,dest.prim);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res)
} else {
if pending(rr.ky) = 0 | sec_failed {
call ref.commit(inp.req.tx,dest.prim);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res)
} else {
call req_chan.send(inp); # if cannot execute, recirculate
}
} else if rr.knd = write {
call ser.serialize(inp.req.tx); # this is ghost!
call fwd_chan.send(inp);
if ~sec_failed {
pending(rr.ky) := pending(rr.ky).next;
var res := rep.exec(inp.req.bd);
}
}
}
} else if rr.knd = write {
call ser.serialize(inp.req.tx); # this is ghost!
call fwd_chan.send(inp);
if ~sec_failed {
pending(rr.ky) := pending(rr.ky).next;
var res := rep.exec(inp.req.bd);
}
}
}
# When we receive a write request on the acknowledgement channel,
# we decrement the pending count of the key.
implement rev_chan.recv(inp : req_msg) {
var rr := inp.req.bd;
if rr.knd = write {
pending(rr.ky) := pending(rr.ky).prev;
}
var rr := inp.req.bd;
if rr.knd = write {
pending(rr.ky) := pending(rr.ky).prev;
}
}
}
@ -276,31 +276,31 @@ module secondary_node(port, fwd_chan, rev_chan, fail_chan, cl_chans) = {
instance rep : replica
instance req_chan : nondup_endpoint(port,req_msg)
var failed : bool
after init {
failed := false;
failed := false;
}
action fail = {
failed := true;
var m : fail_msg;
call fail_chan.send(m);
failed := true;
var m : fail_msg;
call fail_chan.send(m);
}
implement req_chan.recv(inp : req_msg) {
if ~failed {
var rr := inp.req.bd;
if rr.knd = read {
call ref.commit(inp.req.tx,dest.sec);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res);
}
# ignore writes!
}
if ~failed {
var rr := inp.req.bd;
if rr.knd = read {
call ref.commit(inp.req.tx,dest.sec);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res);
}
# ignore writes!
}
}
# When the secondary receives a forwarded write from the primary,
@ -309,13 +309,13 @@ module secondary_node(port, fwd_chan, rev_chan, fail_chan, cl_chans) = {
#
implement fwd_chan.recv(inp : req_msg) {
if ~failed {
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(inp.req.bd);
call cl_chans(inp.cid).send(res);
call rev_chan.send(inp);
}
if ~failed {
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(inp.req.bd);
call cl_chans(inp.cid).send(res);
call rev_chan.send(inp);
}
}
}
@ -351,13 +351,13 @@ object service_spec = {
relation responded(X:txid)
after init {
responded(X) := false;
responded(X) := false;
}
before cl_chans.send(p : client_id, m : response.t) {
assert ~responded(m.tx);
assert m.bd = ref.eval(m.tx);
responded(m.tx) := true;
assert ~responded(m.tx);
assert m.bd = ref.eval(m.tx);
responded(m.tx) := true;
}
}
@ -368,9 +368,9 @@ object mid_spec = {
instance queue : unbounded_queue(txid)
before fwd_chan.rcvr.recv(inp : req_msg) {
assert inp.req.bd = ref.txs(inp.req.tx);
assert inp.req.tx = queue.pop;
call ref.commit(inp.req.tx,dest.sec);
assert inp.req.bd = ref.txs(inp.req.tx);
assert inp.req.tx = queue.pop;
call ref.commit(inp.req.tx,dest.sec);
}
delegate fwd_chan_rcvr_recv[before] -> prim
@ -382,37 +382,37 @@ object mid_spec = {
var sec_failed : bool
after init {
acked(X) := false;
sec_failed := false;
acked(X) := false;
sec_failed := false;
}
before rev_chan.sndr.send(inp : req_msg) {
assert ref.committed(inp.req.tx);
assert ref.txs(inp.req.tx) = inp.req.bd;
assert ~acked(inp.req.tx);
acked(inp.req.tx) := true;
assert ref.committed(inp.req.tx);
assert ref.txs(inp.req.tx) = inp.req.bd;
assert ~acked(inp.req.tx);
acked(inp.req.tx) := true;
}
# If the secondary has failed, then write transactions are commited at the
# moment they are serialized.
after ser.serialize(tx:txid) {
call queue.push(tx);
if sec_failed {
call ref.commit(tx)
}
call queue.push(tx);
if sec_failed {
call ref.commit(tx)
}
}
function req_dest(X:txid) : dest.t
after ref.create(inp : request_body.t, dst:dest.t) returns (tx : txid) {
req_dest(tx) := dst
req_dest(tx) := dst
}
# Here, we set the `sec_failed` flag.
after prim.fail_chan.send(m : fail_msg) {
sec_failed := true;
sec_failed := true;
}
# After a failure of the secondary, the primary is allowed to
@ -420,12 +420,12 @@ object mid_spec = {
# anything.
before ref.commit(tx : txid,dst:dest.t) {
assert ref.txs(tx).knd = read -> req_dest(tx) = dst;
if sec_failed {
assert dst = dst.prim
} else {
assert ref.txs(tx).knd = write -> dst = dest.sec
}
assert ref.txs(tx).knd = read -> req_dest(tx) = dst;
if sec_failed {
assert dst = dst.prim
} else {
assert ref.txs(tx).knd = write -> dst = dest.sec
}
}

Просмотреть файл

@ -34,29 +34,29 @@ type request_kind = {write,read}
object request_body = {
type t = struct {
knd : request_kind,
ky : key,
vl : value
knd : request_kind,
ky : key,
vl : value
}
}
object request = {
type t = struct {
tx : txid,
bd : request_body.t
tx : txid,
bd : request_body.t
}
}
object response_body = {
type t = struct {
vl : value
vl : value
}
}
object response = {
type t = struct {
tx : txid,
bd : response_body.t
tx : txid,
bd : response_body.t
}
}
@ -65,15 +65,15 @@ object response = {
module replica = {
function store(K:key) : value
after init {
store(K) := 0
store(K) := 0
}
action exec(inp : request_body.t) returns (out:response_body.t) = {
if inp.knd = write {
store(inp.ky) := inp.vl;
}
else if inp.knd = read {
out.vl := store(inp.ky);
}
if inp.knd = write {
store(inp.ky) := inp.vl;
}
else if inp.knd = read {
out.vl := store(inp.ky);
}
}
}
@ -100,27 +100,27 @@ object ref = {
relation committed(X:txid)
after init {
next := 0;
committed(X) := false;
next := 0;
committed(X) := false;
}
implement create {
tx := next;
txs(tx) := inp;
next := next + 1;
tx := next;
txs(tx) := inp;
next := next + 1;
}
implement commit {
assert 0 <= tx & tx < next;
assert ~committed(tx);
txres(tx) := rep.exec(txs(tx));
committed(tx) := true;
assert 0 <= tx & tx < next;
assert ~committed(tx);
txres(tx) := rep.exec(txs(tx));
committed(tx) := true;
}
delegate commit
implement eval {
assert committed(tx);
res := txres(tx);
assert committed(tx);
res := txres(tx);
}
delegate eval
@ -140,7 +140,7 @@ object ser = {
relation serialized(X:txid)
after init {
serialized(X) := false;
serialized(X) := false;
}
# To serialzie a write, we must guarantee that transaction exists,
@ -148,10 +148,10 @@ object ser = {
# only serialize write transactions.
implement serialize {
assert 0 <= tx & tx < ref.next;
assert ~serialized(tx);
assert ref.txs(tx).knd = write;
serialized(tx) := true;
assert 0 <= tx & tx < ref.next;
assert ~serialized(tx);
assert ref.txs(tx).knd = write;
serialized(tx) := true;
}
delegate serialize
@ -159,7 +159,7 @@ object ser = {
# until it is serialized.
before ref.commit(tx : txid,dst:dest.t) {
assert ref.txs(tx).knd = write -> serialized(tx);
assert ref.txs(tx).knd = write -> serialized(tx);
}
}
@ -176,8 +176,8 @@ type client_id
object req_msg = {
type t = struct {
cid : client_id,
req : request.t
cid : client_id,
req : request.t
}
}
@ -187,19 +187,19 @@ module client(cid,prim_chan,sec_chan,cl_chans) = {
action client_response(resp : response_body.t, tx : txid)
implement client_request {
var m : req_msg.t;
m.cid := cid;
m.req.tx := ref.create(the_req,the_dst);
m.req.bd := the_req;
if the_dst = dest.prim {
call prim_chan.send(m);
} else {
call sec_chan.send(m);
}
var m : req_msg.t;
m.cid := cid;
m.req.tx := ref.create(the_req,the_dst);
m.req.bd := the_req;
if the_dst = dest.prim {
call prim_chan.send(m);
} else {
call sec_chan.send(m);
}
}
implement cl_chans.recv(resp : response.t) {
call client_response(resp.bd,resp.tx)
call client_response(resp.bd,resp.tx)
}
}
@ -222,14 +222,14 @@ module primary_node(port, fwd_chan, rev_chan, cl_chans) = {
var sec_failed : bool
after init {
pending(K) := 0;
sec_failed := false;
pending(K) := 0;
sec_failed := false;
}
# If we receive a failure message, set `sec_failed`.
implement fail_chan.recv(inp : fail_msg) {
sec_failed := true;
sec_failed := true;
}
@ -237,35 +237,35 @@ module primary_node(port, fwd_chan, rev_chan, cl_chans) = {
# and we no longer wait for acks.
implement req_chan.recv(inp : req_msg.t) {
var rr := inp.req.bd;
var rr := inp.req.bd;
if rr.knd = read {
if pending(rr.ky) = 0 | sec_failed {
call ref.commit(inp.req.tx,dest.prim);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res)
} else {
if pending(rr.ky) = 0 | sec_failed {
call ref.commit(inp.req.tx,dest.prim);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res)
} else {
call req_chan.send(inp); # if cannot execute, recirculate
}
} else if rr.knd = write {
call ser.serialize(inp.req.tx); # this is ghost!
if ~sec_failed {
call fwd_chan.send(inp);
pending(rr.ky) := pending(rr.ky).next;
};
var res := rep.exec(inp.req.bd);
}
}
} else if rr.knd = write {
call ser.serialize(inp.req.tx); # this is ghost!
if ~sec_failed {
call fwd_chan.send(inp);
pending(rr.ky) := pending(rr.ky).next;
};
var res := rep.exec(inp.req.bd);
}
}
# When we receive a write request on the acknowledgement channel,
# we decrement the pending count of the key.
implement rev_chan.recv(inp : req_msg.t) {
var rr := inp.req.bd;
if rr.knd = write {
pending(rr.ky) := pending(rr.ky).prev;
}
var rr := inp.req.bd;
if rr.knd = write {
pending(rr.ky) := pending(rr.ky).prev;
}
}
}
@ -276,33 +276,33 @@ module secondary_node(port, fwd_chan, rev_chan, fail_chan, cl_chans) = {
instance rep : replica
instance req_chan : nondup_endpoint(port,req_msg.t)
var failed : bool
after init {
failed := false;
failed := false;
}
action fail = {
if ~failed {
failed := true;
var m : fail_msg;
call fail_chan.send(m);
}
if ~failed {
failed := true;
var m : fail_msg;
call fail_chan.send(m);
}
}
implement req_chan.recv(inp : req_msg.t) {
if ~failed {
var rr := inp.req.bd;
if rr.knd = read {
call ref.commit(inp.req.tx,dest.sec);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res);
}
# ignore writes!
}
if ~failed {
var rr := inp.req.bd;
if rr.knd = read {
call ref.commit(inp.req.tx,dest.sec);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res);
}
# ignore writes!
}
}
# When the secondary receives a forwarded write from the primary,
@ -311,13 +311,13 @@ module secondary_node(port, fwd_chan, rev_chan, fail_chan, cl_chans) = {
#
implement fwd_chan.recv(inp : req_msg.t) {
if ~failed {
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(inp.req.bd);
call cl_chans(inp.cid).send(res);
call rev_chan.send(inp);
}
if ~failed {
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(inp.req.bd);
call cl_chans(inp.cid).send(res);
call rev_chan.send(inp);
}
}
}
@ -353,13 +353,13 @@ object service_spec = {
relation responded(X:txid)
after init {
responded(X) := false;
responded(X) := false;
}
before cl_chans.send(p : client_id, m : response.t) {
assert ~responded(m.tx);
assert m.bd = ref.eval(m.tx);
responded(m.tx) := true;
assert ~responded(m.tx);
assert m.bd = ref.eval(m.tx);
responded(m.tx) := true;
}
}
@ -370,13 +370,13 @@ object mid_spec = {
instance queue : unbounded_queue(txid)
after ser.serialize(tx:txid) {
call queue.push(tx);
call queue.push(tx);
}
before fwd_chan.rcvr.recv(inp : req_msg.t) {
assert inp.req.bd = ref.txs(inp.req.tx);
assert inp.req.tx = queue.pop;
call ref.commit(inp.req.tx,dest.sec);
assert inp.req.bd = ref.txs(inp.req.tx);
assert inp.req.tx = queue.pop;
call ref.commit(inp.req.tx,dest.sec);
}
delegate fwd_chan_rcvr_recv[before] -> prim
@ -388,32 +388,32 @@ object mid_spec = {
var sec_failed : bool
after init {
acked(X) := false;
sec_failed := false;
acked(X) := false;
sec_failed := false;
}
before rev_chan.sndr.send(inp : req_msg.t) {
assert ref.committed(inp.req.tx);
assert ref.txs(inp.req.tx) = inp.req.bd;
assert ~acked(inp.req.tx);
assert ~sec_failed;
acked(inp.req.tx) := true;
assert ref.committed(inp.req.tx);
assert ref.txs(inp.req.tx) = inp.req.bd;
assert ~acked(inp.req.tx);
assert ~sec_failed;
acked(inp.req.tx) := true;
}
function req_dest(X:txid) : dest.t
after ref.create(inp : request_body.t, dst:dest.t) returns (tx : txid) {
req_dest(tx) := dst
req_dest(tx) := dst
}
before prim.fail_chan.send(m : fail_msg) {
assert ~sec_failed;
assert ~sec_failed;
}
# Here, we set the `sec_failed` flag.
after prim.fail_chan.send(m : fail_msg) {
sec_failed := true;
sec_failed := true;
}
# After a failure of the secondary, the primary is allowed to
@ -421,43 +421,43 @@ object mid_spec = {
# anything.
before ref.commit(tx : txid,dst:dest.t) {
assert ref.txs(tx).knd = read -> req_dest(tx) = dst;
if sec_failed {
assert dst = dst.prim
} else {
assert ref.txs(tx).knd = write -> dst = dest.sec
}
assert ref.txs(tx).knd = read -> req_dest(tx) = dst;
if sec_failed {
assert dst = dst.prim
} else {
assert ref.txs(tx).knd = write -> dst = dest.sec
}
}
object solution = {
# Exercise solution: We maintain an ordered queue of all the
# write requests that have been serialized but not commited.
# Exercise solution: We maintain an ordered queue of all the
# write requests that have been serialized but not commited.
instance pending : unbounded_queue(txid)
instance pending : unbounded_queue(txid)
after ser.serialize(tx:txid) {
call pending.push(tx);
if sec_failed {
call ref.commit(tx,dest.prim)
}
}
after ser.serialize(tx:txid) {
call pending.push(tx);
if sec_failed {
call ref.commit(tx,dest.prim)
}
}
after ref.commit(tx : txid,dst:dest.t) {
if ref.txs(tx).knd = write {
var tmp := pending.pop;
}
}
after ref.commit(tx : txid,dst:dest.t) {
if ref.txs(tx).knd = write {
var tmp := pending.pop;
}
}
# When the secondary says it has failed, we commit all of the
# pending write requests.
# When the secondary says it has failed, we commit all of the
# pending write requests.
after prim.fail_chan.send(m : fail_msg) {
while ~pending.empty {
call ref.commit(pending.first,dest.prim)
}
}
}
after prim.fail_chan.send(m : fail_msg) {
while ~pending.empty {
call ref.commit(pending.first,dest.prim)
}
}
}
}
# We export/import our API.

Просмотреть файл

@ -11,21 +11,21 @@ type request_body
object write_req = {
variant t of request_body = struct {
ky : key,
vl : value
ky : key,
vl : value
}
}
object read_req = {
variant t of request_body = struct {
ky : key
ky : key
}
}
object request = {
type t = struct {
tx : txid,
bd : request_body
tx : txid,
bd : request_body
}
}
@ -38,33 +38,33 @@ object write_resp = {
object read_resp = {
variant t of response_body = struct {
vl : value
vl : value
}
}
object response = {
type t = struct {
tx : txid,
bd : response_body
tx : txid,
bd : response_body
}
}
module replica = {
function store(K:key) : value
after init {
store(K) := 0
store(K) := 0
}
action exec(inp : request_body) returns (out:response_body) = {
if some (r:write_req.t) inp *> r {
store(r.ky) := r.vl;
var wr : write_resp.t;
out := wr
}
else if some (r:read_req.t) inp *> r {
var rr : read_resp.t;
rr.vl := store(r.ky);
out := rr
}
if some (r:write_req.t) inp *> r {
store(r.ky) := r.vl;
var wr : write_resp.t;
out := wr
}
else if some (r:read_req.t) inp *> r {
var rr : read_resp.t;
rr.vl := store(r.ky);
out := rr
}
}
}
@ -85,35 +85,35 @@ module reference = {
relation committed(X:txid)
after init {
next := 0;
committed(X) := false;
serialized(X) := false;
next := 0;
committed(X) := false;
serialized(X) := false;
}
implement create {
tx := next;
txs(tx) := inp;
next := next + 1;
tx := next;
txs(tx) := inp;
next := next + 1;
}
implement serialize {
assert 0 <= tx & tx < next;
assert ~serialized(tx);
serialized(tx) := true;
assert 0 <= tx & tx < next;
assert ~serialized(tx);
serialized(tx) := true;
}
delegate serialize
implement commit {
assert 0 <= tx & tx < next;
assert serialized(tx) & ~committed(tx);
txres(tx) := rep.exec(txs(tx));
committed(tx) := true;
assert 0 <= tx & tx < next;
assert serialized(tx) & ~committed(tx);
txres(tx) := rep.exec(txs(tx));
committed(tx) := true;
}
delegate commit
implement eval {
assert committed(tx);
res := txres(tx);
assert committed(tx);
res := txres(tx);
}
delegate eval
@ -134,11 +134,11 @@ module client(cid,srvr_chan,cl_chans) = {
action client_request(req : request_body)
implement client_request {
var m : req_msg;
m.cid := cid;
m.req.tx := ref.create(req);
m.req.bd := req;
call srvr_chan.send(m);
var m : req_msg;
m.cid := cid;
m.req.tx := ref.create(req);
m.req.bd := req;
call srvr_chan.send(m);
}
}
@ -151,32 +151,32 @@ module primary_node(port, fwd_chan, rev_chan, cl_chans) = {
function pending(K:key) : counter.t
after init {
pending(K) := 0;
pending(K) := 0;
}
implement req_chan.recv(inp : req_msg) {
if some (rr:read_req.t) inp.req.bd *> rr {
if pending(rr.ky) = 0 {
call ref.commit(inp.req.tx);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res)
} else {
if pending(rr.ky) = 0 {
call ref.commit(inp.req.tx);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res)
} else {
call req_chan.send(inp); # if cannot execute, recirculate
}
} else if some (wr:write_req.t) inp.req.bd *> wr {
call ref.serialize(inp.req.tx); # this is ghost!
call fwd_chan.send(inp);
pending(wr.ky) := pending(wr.ky).next;
var res := rep.exec(inp.req.bd);
}
}
} else if some (wr:write_req.t) inp.req.bd *> wr {
call ref.serialize(inp.req.tx); # this is ghost!
call fwd_chan.send(inp);
pending(wr.ky) := pending(wr.ky).next;
var res := rep.exec(inp.req.bd);
}
}
implement rev_chan.recv(inp : req_msg) {
if some (wr:write_req.t) inp.req.bd *> wr {
pending(wr.ky) := pending(wr.ky).prev;
}
if some (wr:write_req.t) inp.req.bd *> wr {
pending(wr.ky) := pending(wr.ky).prev;
}
}
}
@ -184,24 +184,24 @@ module secondary_node(port, fwd_chan, rev_chan, cl_chans) = {
instance rep : replica
instance req_chan : nondup_endpoint(port,req_msg)
implement req_chan.recv(inp : req_msg) {
if some (rr:read_req.t) inp.req.bd *> rr {
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res);
}
# ignore writes!
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(rr);
call cl_chans(inp.cid).send(res);
}
# ignore writes!
}
implement fwd_chan.recv(inp : req_msg) {
call ref.commit(inp.req.tx);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(inp.req.bd);
call cl_chans(inp.cid).send(res);
call rev_chan.send(inp);
call ref.commit(inp.req.tx);
var res : response.t;
res.tx := inp.req.tx;
res.bd := rep.exec(inp.req.bd);
call cl_chans(inp.cid).send(res);
call rev_chan.send(inp);
}
}
@ -217,7 +217,7 @@ instance sec : secondary_node(44201,fwd_chan.rcvr,rev_chan.sndr,cl_chans)
object service_spec = {
before cl_chans.send(p : client_id, m : response.t) {
assert m.bd = ref.eval(m.tx);
assert m.bd = ref.eval(m.tx);
}
}
@ -225,13 +225,13 @@ object mid_spec = {
instance queue : unbounded_queue(txid)
after ref.serialize(tx:txid) {
call queue.push(tx);
call queue.push(tx);
}
before fwd_chan.rcvr.recv(inp : req_msg) {
assert inp.req.bd = ref.txs(inp.req.tx);
assert inp.req.tx = queue.pop;
call ref.commit(inp.req.tx);
assert inp.req.bd = ref.txs(inp.req.tx);
assert inp.req.tx = queue.pop;
call ref.commit(inp.req.tx);
}
delegate fwd_chan_rcvr_recv[before] -> prim

Просмотреть файл

@ -12,7 +12,7 @@ module sequence_numbers = {
interpret t->bv[8]
implement next {
res := seq + 1
res := seq + 1
}
}

Просмотреть файл

@ -19,7 +19,7 @@ object node = {
interpret t -> bv[1]
action next(x:t) returns (y:t) = {
y := x + 1
y := x + 1
}
}
@ -58,18 +58,18 @@ object serv = {
action release(v:node.t) # client releases lock
object spec = {
relation lock(X:node.t)
init lock(X) <-> X = 0
before grant {
assert ~lock(X);
lock(v) := true
}
before release {
assert lock(v);
lock(v) := false
}
relation lock(X:node.t)
init lock(X) <-> X = 0
before grant {
assert ~lock(X);
lock(v) := true
}
before release {
assert lock(v);
lock(v) := false
}
}
}
@ -83,20 +83,20 @@ object proto(me:node.t) = {
relation token
after init {
token := me = 0
token := me = 0
}
implement serv.release {
if token {
token := false;
var pkt : packet.t;
call trans.send(me,node.next(me),pkt)
}
if token {
token := false;
var pkt : packet.t;
call trans.send(me,node.next(me),pkt)
}
}
implement trans.recv(pkt:packet.t) {
token := true;
call serv.grant(me)
token := true;
call serv.grant(me)
}
}

Просмотреть файл

@ -9,10 +9,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "token_ring_trans", "token_r
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A48A9407-CA01-4B56-8D51-303F4FC5F6E1}.Debug|x64.ActiveCfg = Debug|x64

Просмотреть файл

@ -50,7 +50,7 @@ object node = {
interpret t -> bv[1]
action next(x:t) returns (y:t) = {
y := x + 1
y := x + 1
}
}
@ -75,19 +75,19 @@ module transport(lower,packet,id) = {
object spec = {
after init {
sent(D,P) := false
}
after init {
sent(D,P) := false
}
before send {
assert ~sent(dst,pkt);
sent(dst,pkt) := true
}
before send {
assert ~sent(dst,pkt);
sent(dst,pkt) := true
}
before recv {
assert sent(dst,pkt);
sent(dst,pkt) := false
}
before recv {
assert sent(dst,pkt);
sent(dst,pkt) := false
}
}
instance seq_num : sequence_numbers
@ -97,79 +97,79 @@ module transport(lower,packet,id) = {
type mtype = {msg_t, ack_t}
object net_msg = {
type t = struct {
mty : mtype,
src : id,
num : seq_num.t,
payload : packet
}
type t = struct {
mty : mtype,
src : id,
num : seq_num.t,
payload : packet
}
}
object impl(me:id) = {
# Create one outgoing message queue for each host
# and a timout for each queue.
# Create one outgoing message queue for each host
# and a timout for each queue.
instance mq(D:id) : message_queue(net_msg,seq_num)
instance timer(D:id) : timeout_sec
instance mq(D:id) : message_queue(net_msg,seq_num)
instance timer(D:id) : timeout_sec
# Keep track of the latest sequence number sent and received
# on each channel.
# Keep track of the latest sequence number sent and received
# on each channel.
var send_seq(S:id) : seq_num.t
var recv_seq(S:id) : seq_num.t
var send_seq(S:id) : seq_num.t
var recv_seq(S:id) : seq_num.t
init recv_seq(S) = 0 & send_seq(S) = 0
init recv_seq(S) = 0 & send_seq(S) = 0
# Implementations of interface actions
# Implementations of interface actions
implement send(dst:id,pkt:packet) {
var msg : net_msg.t;
var seq : seq_num.t;
msg.mty := msg_t;
msg.src := me;
msg.num := send_seq(dst);
msg.payload := pkt;
send_seq(dst) := send_seq(dst).next;
call mq(dst).enqueue(msg);
call lower.send(me,dst,msg)
}
implement send(dst:id,pkt:packet) {
var msg : net_msg.t;
var seq : seq_num.t;
msg.mty := msg_t;
msg.src := me;
msg.num := send_seq(dst);
msg.payload := pkt;
send_seq(dst) := send_seq(dst).next;
call mq(dst).enqueue(msg);
call lower.send(me,dst,msg)
}
# Receiving a message is the most complicated. First, we send
# an ack. Then, if the sequence number is correct, we call the
# application layer action determined by the message type.
# Receiving a message is the most complicated. First, we send
# an ack. Then, if the sequence number is correct, we call the
# application layer action determined by the message type.
implement lower.recv(msg:net_msg.t) {
var src:id;
var seq:seq_num.t;
seq := msg.num;
src := msg.src;
if seq <= recv_seq(src) & msg.mty ~= ack_t {
var ack : net_msg.t;
ack.mty := ack_t;
ack.src := me;
ack.num := seq;
call lower.send(me,src,ack)
};
if msg.mty = ack_t {
call mq(src).delete_all(seq)
}
else if seq >= recv_seq(src) {
recv_seq(src) := seq_num.next(recv_seq(src));
call recv(me,msg.payload)
}
}
implement lower.recv(msg:net_msg.t) {
var src:id;
var seq:seq_num.t;
seq := msg.num;
src := msg.src;
if seq <= recv_seq(src) & msg.mty ~= ack_t {
var ack : net_msg.t;
ack.mty := ack_t;
ack.src := me;
ack.num := seq;
call lower.send(me,src,ack)
};
if msg.mty = ack_t {
call mq(src).delete_all(seq)
}
else if seq >= recv_seq(src) {
recv_seq(src) := seq_num.next(recv_seq(src));
call recv(me,msg.payload)
}
}
# If an outgoing channel times out and the queue is not empty,
# we pick an arbitrary message in the queue and retransmit it.
# If an outgoing channel times out and the queue is not empty,
# we pick an arbitrary message in the queue and retransmit it.
implement timer.timeout(dst:id) {
if ~mq(dst).empty {
call lower.send(me,dst,mq(dst).pick_one)
}
}
implement timer.timeout(dst:id) {
if ~mq(dst).empty {
call lower.send(me,dst,mq(dst).pick_one)
}
}
}
@ -202,18 +202,18 @@ object serv = {
action release(v:node.t) # client releases lock
object spec = {
relation lock(X:node.t)
init lock(X) <-> X = 0
before grant {
assert ~lock(X);
lock(v) := true
}
before release {
assert lock(v);
lock(v) := false
}
relation lock(X:node.t)
init lock(X) <-> X = 0
before grant {
assert ~lock(X);
lock(v) := true
}
before release {
assert lock(v);
lock(v) := false
}
}
}
@ -227,20 +227,20 @@ object proto(me:node.t) = {
relation token
after init {
token := me = 0
token := me = 0
}
implement serv.release {
if token {
token := false;
var pkt : packet.t;
call trans.send(me,node.next(me),pkt)
}
if token {
token := false;
var pkt : packet.t;
call trans.send(me,node.next(me),pkt)
}
}
implement trans.recv(pkt:packet.t) {
token := true;
call serv.grant(me)
token := true;
call serv.grant(me)
}
}

Просмотреть файл

@ -9,10 +9,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "token_ring_buggy_trans", "t
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A48A9407-CA01-4B56-8D51-303F4FC5F6E1}.Debug|x64.ActiveCfg = Debug|x64

Просмотреть файл

@ -13,19 +13,19 @@ module transport(lower,packet,id) = {
object spec = {
after init {
sent(D,P) := false
}
after init {
sent(D,P) := false
}
before send {
assert ~sent(dst,pkt);
sent(dst,pkt) := true
}
before send {
assert ~sent(dst,pkt);
sent(dst,pkt) := true
}
before recv {
assert sent(dst,pkt);
sent(dst,pkt) := false
}
before recv {
assert sent(dst,pkt);
sent(dst,pkt) := false
}
}
instance seq_num : sequence_numbers
@ -35,79 +35,79 @@ module transport(lower,packet,id) = {
type mtype = {msg_t, ack_t}
object net_msg = {
type t = struct {
mty : mtype,
src : id,
num : seq_num.t,
payload : packet
}
type t = struct {
mty : mtype,
src : id,
num : seq_num.t,
payload : packet
}
}
object impl(me:id) = {
# Create one outgoing message queue for each host
# and a timout for each queue.
# Create one outgoing message queue for each host
# and a timout for each queue.
instance mq(D:id) : message_queue(net_msg,seq_num)
instance timer(D:id) : timeout_sec
instance mq(D:id) : message_queue(net_msg,seq_num)
instance timer(D:id) : timeout_sec
# Keep track of the latest sequence number sent and received
# on each channel.
# Keep track of the latest sequence number sent and received
# on each channel.
var send_seq(S:id) : seq_num.t
var recv_seq(S:id) : seq_num.t
var send_seq(S:id) : seq_num.t
var recv_seq(S:id) : seq_num.t
init recv_seq(S) = 0 & send_seq(S) = 0
init recv_seq(S) = 0 & send_seq(S) = 0
# Implementations of interface actions
# Implementations of interface actions
implement send(dst:id,pkt:packet) {
var msg : net_msg.t;
var seq : seq_num.t;
msg.mty := msg_t;
msg.src := me;
msg.num := send_seq(dst);
msg.payload := pkt;
send_seq(dst) := send_seq(dst).next;
call mq(dst).enqueue(msg);
call lower.send(me,dst,msg)
}
implement send(dst:id,pkt:packet) {
var msg : net_msg.t;
var seq : seq_num.t;
msg.mty := msg_t;
msg.src := me;
msg.num := send_seq(dst);
msg.payload := pkt;
send_seq(dst) := send_seq(dst).next;
call mq(dst).enqueue(msg);
call lower.send(me,dst,msg)
}
# Receiving a message is the most complicated. First, we send
# an ack. Then, if the sequence number is correct, we call the
# application layer action determined by the message type.
# Receiving a message is the most complicated. First, we send
# an ack. Then, if the sequence number is correct, we call the
# application layer action determined by the message type.
implement lower.recv(msg:net_msg.t) {
var src:id;
var seq:seq_num.t;
seq := msg.num;
src := msg.src;
if seq <= recv_seq(src) & msg.mty ~= ack_t {
var ack : net_msg.t;
ack.mty := ack_t;
ack.src := me;
ack.num := seq;
call lower.send(me,src,ack)
};
if msg.mty = ack_t {
call mq(src).delete_all(seq)
}
else if seq = recv_seq(src) {
recv_seq(src) := seq_num.next(recv_seq(src));
call recv(me,msg.payload)
}
}
implement lower.recv(msg:net_msg.t) {
var src:id;
var seq:seq_num.t;
seq := msg.num;
src := msg.src;
if seq <= recv_seq(src) & msg.mty ~= ack_t {
var ack : net_msg.t;
ack.mty := ack_t;
ack.src := me;
ack.num := seq;
call lower.send(me,src,ack)
};
if msg.mty = ack_t {
call mq(src).delete_all(seq)
}
else if seq = recv_seq(src) {
recv_seq(src) := seq_num.next(recv_seq(src));
call recv(me,msg.payload)
}
}
# If an outgoing channel times out and the queue is not empty,
# we pick an arbitrary message in the queue and retransmit it.
# If an outgoing channel times out and the queue is not empty,
# we pick an arbitrary message in the queue and retransmit it.
implement timer.timeout(dst:id) {
if ~mq(dst).empty {
call lower.send(me,dst,mq(dst).pick_one)
}
}
implement timer.timeout(dst:id) {
if ~mq(dst).empty {
call lower.send(me,dst,mq(dst).pick_one)
}
}
}