- exp_comparison_plot.py
- This file contains the code to generate the plots for the comparison of the Deadline mode with FIFO vs Shortest Deadline first.
- plot_frac_queue_len.py
- This file contains the code to generate the plots for the fractional queue length (For Theoretical and Simulation).
- queue_sim_dl.py
- This file contains the code to simulate the queue with deadline mode with EDF (Earliest Deadline First).
- queue_sim_sh_sjf.py
- This file contains the code to simulate the queue with Shortest Job First.
To ensure that the environment is properly set up, please follow the steps below:
Run the following script to create a Python virtual environment and install all the necessary dependencies:
bash requirements.shAlternatively, you can manually install the dependencies listed in requirements.txt if you prefer.
To simulate the experiments related to queues, execute the following script:
cd Assignment1 && bash queue_experiments.shThis will run simulations with weibull distribution and generate the required data files for further processing.
cd Assignment1 && bash queue_experiments_a_weibull.shThis will run simulations with shortest job first and generate the required data files for further processing.
cd Assignment1 && bash queue_experiments_sch_sjf.shThis will run simulations with deadline mode and generate the required data files for further processing.
cd Assignment1 && bash queue_experiments_dl.shThis will generate visualizations related to the queue waiting time.
cd Assignment1 && bash queue_plot.shTo plot the fractional queue length, run the following script.
There are two approaches to run this script:
- Run the script to produce theoretical results
- Run the script to produce simulation results (commented out in the script)
cd Assignment1 && bash queue_plot_frac_len.shThis will create plots for the fractional queue length over time.
If you want to clean up the environment, deactivate the Python virtual environment and remove any generated files.
deactivateThis repository contains a discrete-event simulation system for experimenting with data backup and redundancy in various network configurations. The simulation models a set of nodes (or a single client plus multiple servers) that:
- Fail and recover randomly, based on a specified lifetime distribution.
- Exchange data blocks (upload/download) using erasure coding parameters (
n,k). - Optionally adapt how many blocks (
n_active) they actually store if redundancy becomes threatened (“dynamic n”).
You can test two main scenarios:
- Peer-to-Peer (P2P):
Each node stores its own erasure-coded data across other peers. - Client-Server:
A single client stores data on multiple dedicated servers.
-
storage.py- Main simulation driver and entry point.
- Defines the
Backupclass (a subclass ofSimulation) that schedules node events. - Implements the
Nodeclass for node state, upload/download speeds, etc. - Contains event subclasses (
Online,Fail,BlockBackupComplete, etc.) that handle specific behaviors. - Includes the
main()function for command-line argument parsing and launching simulations.
-
discrete_event_sim.py- Provides the discrete-event simulation framework.
- Defines the
Simulationbase class with:- An event queue (priority queue, using
heapq). - Methods to
scheduleevents andrunthem until a time limit is reached.
- An event queue (priority queue, using
- Includes plotting utilities (using
matplotlib) to parse simulation logs and generate line plots of failures, recoveries, backups, and data losses over time.
-
Configuration Files
p2p.cfg: Settings for peer-to-peer simulations (e.g., number of peers, speeds,n,k, etc.).client_server.cfg: Settings for a mixed client-server simulation.
-
storage.sh(Bash script)- Example script showing how to invoke
storage.pywith different scenarios and flags (e.g.,--n-active). - Creates
logs/andplots/directories, then saves logs and plots there.
- Example script showing how to invoke
-
logs/- Directory where
.logfiles from simulations are stored. This directory is produced when you run the storage.sh file. This directory is needed when plotting the diagrams.
- Directory where
-
plots/- Directory where
.pngplots (failures over time, recoveries, backups, data-loss, etc.) are saved. - This directory is produced when you run the storage.sh file.
- Directory where
-
Python 3.7+
Make sure you have Python 3.7 or higher installed. -
Optional: Create a Virtual Environment
python3 -m venv venv source venv/bin/activate -
Install Required Packages
You can install the required Python libraries with:
pip install -r requirements.txt
To run the simulation with a specific configuration, use the following command (you can change this part in the storage.sh file, run the code using that file for better results):
python3 storage.py p2p.cfg --max-t "100 years" --verboseIf you want to simulate using "n_active" feature, try the following command:
python3 storage.py p2p.cfg --max-t "100 years" --verbose --n-active 5 --tolerance 1 # or whatevet number you want--tolerance 1 means less than how many redundant blocks you think might put us in the danger zone. Also you can simply run storage.sh or modify it with the desired configs.
The simulation supports a dynamic redundancy strategy where nodes can incrementally activate more blocks (n_active) as redundancy becomes insufficient. This feature:
- Reduces overhead: Nodes begin with fewer active blocks, requiring fewer backup operations initially.
- Maintains reliability: The system dynamically adjusts
n_activeto meet redundancy requirements, preventing excessive data loss.
The simulation produces visual outputs for quick analysis of system performance:
- Failures over time: Helps assess the failure rates of nodes in the system.
- Recoveries over time: Tracks how often nodes recover from failures.
- Backups over time: Shows the volume of backup operations under different scenarios.
- Data Losses over time: Highlights the system's ability to prevent unrecoverable data loss.
n and k are erasure-coding parameters:
n: Total number of blocks (data + parity) used to store the data.k: Number of blocks required to recover the full data.
For example, if n=10 and k=8, there are 2 parity blocks. Any 8 out of the 10 blocks can reconstruct the original data.
n_active represents the number of blocks a node actively uses at a given time:
- By default,
n_active = n(all blocks are used). - Dynamic
n_activeallows nodes to start with fewer active blocks and increase the count only when redundancy becomes insufficient.
Yes, you can edit the .cfg files to set custom parameters (e.g., node counts, lifetimes, speeds, and storage sizes). You can also modify the Python code to add new event types or redundancy strategies.