1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
|
\documentclass{article}
\usepackage[backend=biber]{biblatex}
\usepackage{listings}
\usepackage{xcolor}
\definecolor{bgcolor}{rgb}{0.97, 0.97, 0.95}
\lstdefinestyle{lststyle}{
backgroundcolor=\color{bgcolor},
tabsize=2,
}
\lstset{style=lststyle}
\lstset{language=C}
\title{Software-Failure-Tolerant and Highly-Available Design of the Distributed Emergency Response Management System}
\addbibresource{references.bib}
\author{}
\begin{document}
\maketitle
\begin{center}
\begin{tabular}{l l l}
\textbf{Name} & \textbf{Student ID} & \textbf{Module} \\ \hline\hline
Shaza Ahmed & TODO & TODO \\ \hline
Sam Anthony & 40271987 & Sequencer \\ \hline
Bence Matajsz & TODO & Testing \\ \hline
Vijaykumar Patel & TODO & Front end \\ \hline
\end{tabular}
\end{center}
\section{Introduction}
TODO
\section{Architecture}
TODO
\section{Front end}
TODO
\section{Replica manager}
TODO
\section{Sequencer}
The purpose of the sequencer is to ensure that requests are delivered to all of the replicas in the same (total) order.
This ensures sequential consistency of the system because all replicas perform the same computations in the same order.
\paragraph{}
The FE delivers requests to the RMs via \emph{totally ordered reliable multicast}.
When the FE receives a request from a client, it sends the request to the multicast group.
All of the RMs, as well as the sequencer, are members of the group, so they receive the request.
When a RM receives a request, it does not deliver it to the replica immediately.
Rather, it adds the message to a \emph{holdback queue} and waits to receive an \emph{order message} from the sequencer.
The sequencer is also a member of the multicast group, but it has a special function.
When it receives a message, it multicasts an \emph{order message} containing the ID of the message it has just received.
When a RM receives an order message, it inspects the ID attached to it and removes the associated message from the holdback queue and delivers it to the replica.
\paragraph{}
The FE and RMs need not be aware of any of this behavior because it is encapsulated in the totally-ordered reliable multicast class.
As far as the FE knows, it is just ``sending a request to all of the RMs."
And from the perspective of an RM, it is just ``receiving a request from the FE."
They can be sure that they are reliably sending and receiving requests in the proper order, without worrying about the implementation details, or even knowing of the existence of the sequencer.
\paragraph{}
The totally ordered multicast protocol is built on top of a reliable multicast mechanism---an implementation of the Trans Protocol, ``[which] uses a combination of positive and negative acknowledgement strategies to achieve efficient reliable broadcast or multicast communication" \cite{melliar-smith-trans}.
\paragraph{}
\textbf{Sequencer pseudocode:}
\begin{lstlisting}
type dataMsg struct {
id int
data
}
type orderMsg struct {
id int
seq int
}
class groupMember {
seq := 0
holdback := new Queue[dataMsg]
deliver := new Queue[dataMsg]
rMulticast := new Trans
multicast(m dataMsg) {
rMulticast.send(m)
}
on rMulticast.recv(m dataMsg) {
holdback.enqueue(m)
}
on rMulticast.recv(m orderMsg) {
wait until m.id in holdback && seq == m.seq
data := delete(m.id, holdback)
deliver.enqueue(data)
seq++
}
}
// Sequencer is also a member of the multicast group.
class sequencer {
seq := 0
rMulticast := new Trans
on rMulticast.recv(m dataMsg) {
order := orderMsg{m.id, seq}
rMulticast.send(order)
seq++
}
}
\end{lstlisting}
\textbf{Reliable multicast (Trans) pseudocode:}
\begin{lstlisting}
// message
type m struct {
id mid
sender pid
seq int // sequence number
positiveAcks []mid
negativeAcks []mid
data
}
type mid "message ID"
type pid "process ID"
var (
positiveAcks []mid
negativeAcks []mid
received []m
retransmissions []mid
lastSend time
)
send(m) {
pkt := (m, positiveAcks, negativeAcks)
multicast(pkt)
positiveAcks = []
go timeout(m)
lastSend = now()
}
timeout(m) {
sleep until timeout
if m not in positiveAcks {
insert(m, retransmissions)
}
}
recv(m) {
insert(m.id, positiveAcks)
insert(m, received)
if m.id in negativeAcks {
delete(m.id, negativeAcks)
}
if m.id in retransmissions {
delete(m.id, retransmissions
}
for each mid in m.positiveAcks {
delete(mid, positiveAcks)
if mid not in received {
insert(mid, negativeAcks)
}
}
for each mid in m.negativeAcks {
if mid in received {
insert(mid, retransmissions)
} else {
insert(mid, negativeAcks)
}
}
acks := union(positiveAcks, negativeAcks)
for each ack in acks s.t.
sender(ack) == sender(m)
&& m.seq > ack.seq+1 {
insert(m.id, negativeAcks)
}
}
retransmit() {
forever {
wait until
timeSince(lastSend) > threshold
&& len(retransmissions) > 0
mid := pop(retransmissions)
m := received[mid]
send(m)
}
}
// Observable Predicate for Delivery.
// The process that broadcast c has received and acked
// message a at the time of broadcasting c.
// All assertions must hold in order to return true.
OPD(a, c m) bool {
assert (t.e. sequence [a, ..., c])
for each i, m in sequence, except a {
predecessor := sequence[i-1]
assert (
predecessor in m.positiveAcks
|| m.sender == precessor.sender)
assert (m not in c.negativeAcks)
}
}
// Partial order.
// All assertions must hold in order to return true.
(c m) follows(b m) bool {
assert OPD(b, c)
for all a in received {
if OPD(a, b) {
assert OPD(a, c)
}
}
}
\end{lstlisting}
\section{Testing}
TODO
\printbibliography
\end{document}
|