0% found this document useful (0 votes)
3 views11 pages

UCS1701 - Distributed Systems

The document discusses the design and implementation of a vector clock for ad-hoc distributed systems, focusing on the challenges posed by dynamic processes in environments like vehicular networks. It outlines the adaptation of conventional vector clocks to accommodate processes joining and leaving the system, including rules for updating and maintaining the vector clock. The document also provides examples illustrating the functionality of the adapted design and presents a theoretical proof of its correctness in preserving event ordering and handling concurrency.

Uploaded by

rickyballs07
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views11 pages

UCS1701 - Distributed Systems

The document discusses the design and implementation of a vector clock for ad-hoc distributed systems, focusing on the challenges posed by dynamic processes in environments like vehicular networks. It outlines the adaptation of conventional vector clocks to accommodate processes joining and leaving the system, including rules for updating and maintaining the vector clock. The document also provides examples illustrating the functionality of the adapted design and presents a theoretical proof of its correctness in preserving event ordering and handling concurrency.

Uploaded by

rickyballs07
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 11

UCS1701 - Distributed Systems

Name - Alamelu Kannan


Reg No. - 3122215001007

Design a Vector Clock for Ad-Hoc Distributed Systems

Consider a modern ad-hoc distributed system like vehicular or mobile networks. As the
characteristics of ad-hoc systems vary from the conventional distributed systems, the design
challenges of ad-hoc systems should be studied for renovating the insight towards key
technological shifts.

a. Adapt the conventional representation of vector clocks to suit the ad-hoc distributed system.

Dynamic Vector:
The number of processes in the system is not constant. So the vector cannot have a fixed
size. Maintain a counter variable and when a node joins the system, increment the counter
variable and store the clock value and process ID. When a process leaves, decrement the
counter, remove the clock value from the vector and shift all the values in the vector.

Vector Clock Updates:


When messages are exchanged, update the vector clock using the timestamp.

Stagnant Process:
Maintain a TTL value which when expired removes the corresponding process’s entry from
the vector clock. If any message exchange takes place involving that process, the vector
clock entry would be updated.

An alternative method would be to make a new node or a leaving node broadcast a


message advertising its entry or departure.

Causality:
Maintain a time window. The processes occurring within that window are
considered concurrent and not causal.
Renewing Process Clock Value:
When timestamp is passed, comparison has to be done with the values in the timestamp
and the values in the vector clock of the receiver process. This helps to check if outdated
processes are present in the vector clock. If any process’s entry has expired, but is present in
either the timestamp or the vector clock entry, it will get renewed.

b. Formulate the implementation rules for the adapted design of vector clock
synchronization concerning the design challenges of the ad-hoc distributed system.

All the processes should maintain a queue initially with its own identifier in the
queue and clock value. Vector is an array of structures and for process i will look
like [{i, 0, t, 1}] Ci.id = i, Ci.clock = 0 and Ci.ttl = t, Ci.counter = 1

For process i, Ci.ttl = ထ

Sending Event/All events:


Ci.id == i -> Ci.clock++ Ck.ttl--

Receiving Event:
Sender -> i
Receiver -> j
Other Processes -> k
Time stamp sent -> tm

If process id is not in the vector clock of j, then


++counter
Cj[counter].id = k
Cj[counter].clock = Clock of value of that process in the time stamp
Else Cj.id == k
Cj.clock = max(Cj.clock, tm.clock)

Expired Process:
If Ci.id == k and Ci.ttl == 0, remove it from the queue, Ci.counter--.
c . Elaborate the working of the adapted design through a relevant example.

To simulate the working of the newly designed vector clock using the provided rules, we'll
create examples for various degrees of ad-hocness. The vector clock is represented as an
array of structures, where each structure holds the process ID, the clock value, the
time-to-live (TTL), and a counter. Let's explore the behavior of this vector clock in different
scenarios.

Example 1: Less Ad-Hoc Scenario


Let's consider three processes: A, B, and C.

- Initial vector clocks:


- A: [{A, 0, 3, 1}]
- B: [{B, 0, 3, 1}]
- C: [{C, 0, 3, 1}]

1. Process A sends a message to B:


- A's vector clock: [{A, 1, 2, 1}]
- B receives the message and updates its vector clock: [{B, 1, 2, 1}]

2. Process C joins the network:


- C's vector clock: [{C, 0, 2, 1}, {A, 1, 2, 1}, {B, 1, 2, 1}]

3. Process A sends another message to B:


- A's vector clock: [{A, 2, 1, 2}]
- B receives the message and updates its vector clock: [{B, 2, 1, 2}]

In this less ad-hoc scenario, the vector clocks remain straightforward, and the structure of
the processes is relatively stable.

Example 2: Moderately Ad-Hoc Scenario

Let's consider processes A, B, C, and D.

- Initial vector clocks:


- A: [{A, 0, 3, 1}]
- B: [{B, 0, 3, 1}]
- C: [{C, 0, 3, 1}]
- D: [{D, 0, 3, 1}]

1. Process A sends a message to B:


- A's vector clock: [{A, 1, 2, 1}]
- B receives the message and updates its vector clock: [{B, 1, 2, 1}]

2. Process C joins and leaves the network:


- C's vector clock: [{C, 0, 2, 1}, {A, 1, 2, 1}, {B, 1, 2, 1}]
- Later, C leaves the network.

3. Process D joins the network:


- D's vector clock: [{D, 0, 2, 1}, {A, 1, 2, 1}, {B, 1, 2, 1}]

4. Process A sends another message to B:


- A's vector clock: [{A, 2, 1, 2}]
- B receives the message and updates its vector clock: [{B, 2, 1, 2}]

In this moderately ad-hoc scenario, the vector clocks handle the dynamic nature of
the environment with occasional node departures and arrivals.

Example 3: Highly Ad-Hoc Scenario

Let's consider processes A, B, C, D, E, and F.

- Initial vector clocks:


- A: [{A, 0, 3, 1}]
- B: [{B, 0, 3, 1}]
- C: [{C, 0, 3, 1}]
- D: [{D, 0, 3, 1}]
- E: [{E, 0, 3, 1}]
- F: [{F, 0, 3, 1}]

1. Process A sends a message to B:


- A's vector clock: [{A, 1, 2, 1}]
- B receives the message and updates its vector clock: [{B, 1, 2, 1}]

2. Process C joins and leaves the network:


- C's vector clock: [{C, 0, 2, 1}, {A, 1, 2, 1}, {B, 1, 2, 1}]
- Later, C leaves the network.
3. Process D and E join the network and leave frequently, causing rapid updates in their
vector clocks.

4. Process A sends another message to B:


- A's vector clock: [{A, 2, 1, 2}]
- B receives the message and updates its vector clock: [{B, 2, 1, 2}]

In this highly ad-hoc scenario, the vector clocks cope with the frequent changes in the network
structure, demonstrating their adaptability to rapidly changing conditions and maintaining event
ordering. The use of TTL ensures that expired processes are removed from the queue, helping
to manage the vector clock's size.

d. Code generated from Copilot/ ChatGPT for Conventional Vector Clock will be provided.
Perform the implementation for a, b and c

Python

class AdHocVectorClock:

def __init__(self, process_id, ttl=5):

"""Initializes the vector clock for a process with a TTL value."""

self.process_id = process_id

self.clock = {process_id: 0}

self.ttl = ttl # Time-to-Live for each process

self.ttl_tracker = {process_id: ttl}

def add_process(self, new_process_id, ttl=5):

"""Adds a new process to the vector clock with its TTL."""

if new_process_id not in self.clock:

self.clock[new_process_id] = 0

self.ttl_tracker[new_process_id] = ttl
print(f"Process {new_process_id} added to the vector clock.")

def remove_process(self, process_id):

"""Removes a process from the vector clock when TTL expires or the
process leaves."""

if process_id in self.clock:

del self.clock[process_id]

del self.ttl_tracker[process_id]

print(f"Process {process_id} removed from the vector clock.")

def decrement_ttl(self):

"""Decrements TTL for all processes and removes them if TTL hits
zero."""

to_remove = []

for process in self.ttl_tracker:

self.ttl_tracker[process] -= 1

if self.ttl_tracker[process] <= 0:

to_remove.append(process)

for process in to_remove:

self.remove_process(process)
def update(self, process_id):

"""Increments the clock for the process that sends an event."""

if process_id in self.clock:

self.clock[process_id] += 1

def send_event(self):

"""Handles sending an event, increments the clock for the process."""

self.update(self.process_id)

return self.clock.copy()

def receive_event(self, sender_clock):

"""Handles receiving an event, updates the clock based on the received


clock."""

self.update(self.process_id) # Increment receiver's clock

for process, timestamp in sender_clock.items():

if process in self.clock:

self.clock[process] = max(self.clock[process], timestamp)

else:

self.add_process(process)

self.clock[process] = timestamp

def get_clock(self):
"""Returns the current vector clock."""

return self.clock

def display_clock(self):

"""Prints the current vector clock."""

print(f"Process {self.process_id} Clock: {self.clock} | TTLs:


{self.ttl_tracker}")

# Example Simulation

# Initialize vector clocks for 3 processes in an ad-hoc system.

vc_A = AdHocVectorClock('A')

vc_B = AdHocVectorClock('B')

vc_C = AdHocVectorClock('C')

# Step 1: A sends an event.

vc_A.send_event()

vc_A.display_clock()

# Step 2: B receives the event from A.

vc_B.receive_event(vc_A.get_clock())

vc_B.display_clock()
# Step 3: C joins the network.

vc_A.add_process('C')

vc_B.add_process('C')

vc_A.display_clock()

vc_B.display_clock()

# Step 4: A sends another event.

vc_A.send_event()

vc_A.display_clock()

# Step 5: C leaves the network (TTL expiration).

vc_A.decrement_ttl()

vc_A.display_clock()

vc_B.decrement_ttl()

vc_B.display_clock()

# Step 6: B receives another event from A.

vc_B.receive_event(vc_A.get_clock())

vc_B.display_clock()
e. Provide a theoretical proof that illustrates the working of proposed algorithm.

The adapted vector clock for ad-hoc distributed systems introduces dynamic processes with
varying lifespans (Time-to-Live) and allows for processes to join or leave the system arbitrarily.
The goal is to show that the vector clock maintains causality, preserves event ordering, and
adapts effectively to process dynamics. Here's a formal proof.

1. Preservation of Event Ordering (Causality)

In a distributed system, the vector clock ensures that if an event e1 causally precedes event e2,
the vector timestamp of e1 will be smaller than that of e2. This can be written formally as:

𝑒1→𝑒2⟹𝑉(𝑒1) < 𝑉(𝑒2)

For a process P, assume it sends an event e1 and then event e2 in that order. Each time an
event is sent, the process's clock is incremented. This guarantees that the local timestamp at P
for e1 is smaller than for e2:

𝑉(𝑒1)𝑃​ < 𝑉(𝑒2)𝑃​

Next, assume process P1 sends an event e1 to process P2. When P2 receives the event, it
updates its vector clock by taking the maximum of its current timestamp and the incoming one
for each process:

𝑉(𝑒2)𝑃​2 = 𝑚𝑎𝑥(𝑉(𝑒1)𝑃​2, 𝑉(𝑒1)𝑃​1)

This ensures that if e1 occurs before e2, the vector clock at P2 is updated such that the
timestamp for e1 is always smaller than for any subsequent event e2.

2. Concurrent Events

Concurrent events are events that occur in different processes that do not causally affect each
other. In an ad-hoc distributed system, two processes P1 and P2 can send events
independently. Since these events do not have a causal relationship, their vector clocks will
reflect this independence:

If event e1 at P1 and event e2 at P2 are concurrent, the vector clocks are incomparable,
meaning neither is smaller or greater than the other:

𝑉(𝑒1)𝑃​1∥𝑉(𝑒2)𝑃​2

This property holds even with dynamic processes joining or leaving the system because the
vector clocks only maintain relevant process entries. When a process joins, it adds itself to the
clock without affecting the ordering of previous events. When a process leaves, its entry is
removed, but the event ordering of other processes remains unaffected.

3. Handling Dynamic Process Join/Leave

The system dynamically adjusts the vector clock size by adding new processes upon joining
and removing them when they leave or when their TTL expires.

For a new process P3 joining the system, the adapted vector clock adds a new entry for P3 with
an initial timestamp of 0. This allows P3 to participate in event exchanges without affecting the
ordering of prior events.

If a process P3 leaves, it is removed from the vector clock. This removal is consistent with the
system’s requirement to maintain event causality, as the removal of P3 only eliminates stale
processes and their associated timestamps. The remaining processes still preserve the causal
relationships among themselves, as the vector clock comparison only focuses on relevant
(non-expired) processes.

4. Validity of Vector Clock Comparisons

Given that vector clocks rely on comparing timestamps across processes, we need to show that
this comparison is valid even when processes dynamically join or leave. For any two processes
P1 and P2, the comparison is valid as long as the vector clock contains entries for all active
processes. When P3 leaves, its timestamp is no longer relevant, and removing it does not affect
the comparison of events between P1 and P2.

Formally, the comparison for causality is based on:

𝑉(𝑒1)𝑃​1[𝑖]≤𝑉(𝑒2)𝑃​2[𝑖], ∀𝑖

Where i is any active process at the time of the event comparison. The TTL mechanism
ensures that stale processes are removed and the vector clock remains a manageable size
without impacting the correctness of the system.

Conclusion

The adapted vector clock for an ad-hoc distributed system correctly preserves causality,
maintains concurrent event independence, and handles the dynamic nature of processes joining
and leaving the system. The theoretical properties of vector clocks—such as event ordering and
the ability to handle concurrency—are maintained despite the system's dynamic nature.
Therefore, the design of the adapted vector clock is provably correct for use in ad-hoc
distributed systems.

You might also like