19 const char* RESET =
"\033[0m";
20 const char* CYAN =
"\033[36m";
21 const char* GREEN =
"\033[32m";
22 const char* YELLOW =
"\033[33m";
23 const char* MAGENTA =
"\033[35m";
24 const char* BOLD =
"\033[1m";
25 const char* RED =
"\033[31m";
29 std::ostringstream oss;
31 oss << CYAN <<
"[" << RESET << BOLD <<
currentTime_ << RESET << CYAN <<
"]" << RESET
32 <<
" " << colorCode << msg << RESET <<
"\n";
47 rng_(std::random_device()()),
49 timeDist_(config.minProcessingTime, config.maxProcessingTime),
58 for (
int i = 0; i < initialServerCount; ++i) {
66 std::ostringstream oss;
83 for (
int i = 0; i < count; ++i) {
87 std::ostringstream oss;
88 oss <<
"Prefilled queue with " << count <<
" requests";
89 log(GREEN, oss.str().c_str());
97 std::vector<int> blockedOctets;
98 if (!
config_.blockedOctets.empty()) {
99 blockedOctets =
config_.blockedOctets;
101 blockedOctets = {192, 255};
104 auto isBlockedFirstOctet = [](
int octet,
const std::vector<int>& blocked) ->
bool {
105 return std::find(blocked.begin(), blocked.end(), octet) != blocked.end();
108 int firstOctet = std::stoi(req.
ipIn.substr(0, req.
ipIn.find(
'.')));
109 if (isBlockedFirstOctet(firstOctet, blockedOctets)) {
110 std::ostringstream oss;
111 oss <<
"Request blocked (bad octet) from " << req.
ipIn;
113 log(RED, oss.str().c_str());
120 std::ostringstream oss;
121 oss <<
"New request added (" << req.
jobType <<
") from " << req.
ipIn;
122 log(GREEN, oss.str().c_str());
134 server->assignRequest(req);
140 int numServers =
static_cast<int>(
servers_.size());
147 if (queueSize < minQueueThreshold_ && numServers > 1) {
149 [](
const std::unique_ptr<WebServer>& s) { return !s->isBusy(); });
154 std::ostringstream oss;
155 oss <<
"Removed server. Active: " <<
static_cast<int>(
servers_.size())
157 <<
" (Queue: " << queueSize <<
")";
158 log(YELLOW, oss.str().c_str());
164 std::ostringstream oss;
165 oss <<
"Added server. Active: " <<
static_cast<int>(
servers_.size())
167 <<
" (Queue: " << queueSize <<
")";
168 log(YELLOW, oss.str().c_str());
181 std::ostringstream oss;
182 int active =
static_cast<int>(
servers_.size());
184 oss << CYAN <<
"[" << RESET << BOLD <<
currentTime_ << RESET << CYAN <<
"]" << RESET
185 <<
" " << BOLD <<
"Active: " << active << RESET <<
" | "
197 if (server->isFinished()) {
198 std::ostringstream oss;
199 oss <<
"Server " << server->getId() <<
" finished request";
200 log(MAGENTA, oss.str().c_str());
215 int finalServerCount =
servers_.size();
216 std::ostringstream oss;
218 oss <<
"\n" << BOLD <<
"Simulation Summary:" << RESET <<
"\n"
219 <<
"Task time range: " <<
config_.minProcessingTime <<
" - " <<
config_.maxProcessingTime <<
"\n"
220 << MAGENTA <<
"Total Requests Processed: " <<
totalProcessed_ << RESET <<
"\n"
221 << YELLOW <<
"Total Requests still in Queue: " <<
requestQueue_.size() << RESET <<
"\n"
223 << RED <<
"Total Requests Blocked: " <<
totalBlocked_ << RESET <<
"\n"
224 << GREEN <<
"Servers Added: " <<
serversAdded_ << RESET <<
"\n"
226 << BOLD <<
"Started with " << initialServerCount <<
" servers" << RESET <<
"\n"
227 << BOLD <<
"Ended with " << finalServerCount <<
" servers" << RESET <<
"\n\n";
229 oss <<
"\nSimulation Summary:\n"
230 <<
"Task time range: " <<
config_.minProcessingTime <<
" - " <<
config_.maxProcessingTime <<
"\n"
232 <<
"Total Requests still in Queue: " <<
requestQueue_.size() <<
"\n"
237 <<
"Started with " << initialServerCount <<
" servers\n"
238 <<
"Ended with " << finalServerCount <<
" servers\n\n";
const char STREAMING_JOB
Job type character for streaming jobs.
const char PROCESS_JOB
Job type character for process jobs.
Defines the LoadBalancer class for the simulation.
Defines the Logger class for console and file output.
void generateRequest()
Possibly generate a new request (based on probability).
void scaleServers()
Add or remove servers based on queue size thresholds.
std::uniform_int_distribution< int > timeDist_
std::string generateRandomIP()
Generate a random IP address string (x.x.x.x format).
LoadBalancerConfig config_
std::vector< std::unique_ptr< WebServer > > servers_
void assignRequests()
Assign queued requests to idle servers.
void log(const char *colorCode, const char *msg) const
Log a message with optional color code.
std::uniform_int_distribution< int > octetDist_
void run(int totalClockCycles)
Run the simulation for the specified number of clock cycles.
LoadBalancer(int initialServers, const LoadBalancerConfig &config)
Construct the load balancer with initial servers and config.
void prefillQueue(int count)
Prefill the request queue with random requests.
std::uniform_int_distribution< int > jobTypeDist_
std::bernoulli_distribution requestDist_
void printSummary(int initialServerCount) const
Print simulation summary statistics.
std::queue< Request > requestQueue_
Request createRandomRequest()
Create a random request with random IPs and processing time.
int requestsAddedToQueue_
static void log(const std::string &message)
Write a message to both console and log file.
Configuration parameters for the load balancer simulation.
Represents a single request/job in the load balancer simulation.