void PDQ_SetVisits_p(char *nodename, char *workname, double *visits, double *service) { extern NODE_TYPE *node; extern int demand_ext; extern int PDQ_DEBUG; char *p = "PDQ_SetVisits()"; // Added by NJG on Wednesday, June 1, 2016 // Needed in case SetVisits used instead of SetDemand demands = 1; // non-zero since SetDemand equivalent now called if (PDQ_DEBUG) { PRINTF("nodename : %s workname : %s visits : %f service : %f\n", nodename, workname, *visits, *service); } if (demand_ext == VOID || demand_ext == VISITS) { node[getnode_index(nodename)].visits[getjob_index(workname)] = *visits; node[getnode_index(nodename)].service[getjob_index(workname)] = *service; node[getnode_index(nodename)].demand[getjob_index(workname)] = (*visits) * (*service); demand_ext = VISITS; } else errmsg(p, "Extension conflict"); } // PDQ_SetVisits
double PDQ_GetQueueLength(char *device, char *work, int should_be_class) { char *p = "PDQ_GetQueueLength()"; extern char s1[]; // Initialize vars to suppress compiler warnings double q = 0.0; double x = 0.0; int c = 0; int k = 0; // Added by NJG on Wednesday, August 19, 2015 if (!streams) PRINTF("PDQ_GetQueueLength warning: No PDQ workload defined.\n"); if (!nodes) PRINTF("PDQ_GetQueueLength warning: No PDQ nodes defined.\n"); if (!demands) PRINTF("PDQ_GetQueueLength warning: No PDQ service demands defined.\n"); c = getjob_index(work); x = PDQ_GetThruput(should_be_class, work); for (k = 0; k < nodes; k++) { if (strcmp(device, node[k].devname) == 0) { q = node[k].resit[c] * x; return (q); } } sprintf(s1, "Unknown device %s", device); errmsg(p, s1); g_debug("PDQ_GetQueueLength - Bad double return"); return -1.0; } /* PDQ_GetQueueLength */
double PDQ_GetResidenceTime(char *device, char *work, int should_be_class) { char *p = "PDQ_GetResidenceTime()"; extern char s1[]; // Initialize vars to suppress compiler warnings double r = 0.0; int c = 0; int k = 0; // Added by NJG on Wednesday, August 19, 2015 if (!streams) PRINTF("PDQ_GetResidenceTime warning: No PDQ workload defined.\n"); if (!nodes) PRINTF("[PDQ_GetResidenceTime warning: No PDQ nodes defined.\n"); if (!demands) PRINTF("[PDQ_GetResidenceTime warning: No PDQ service demands defined.\n"); c = getjob_index(work); for (k = 0; k < nodes; k++) { if (strcmp(device, node[k].devname) == 0) { r = node[k].resit[c]; return (r); } } sprintf(s1, "Unknown device %s", device); errmsg(p, s1); g_debug("PDQ_GetResidenceTime: Returning bad double\n"); return -1.0; } /* PDQ_GetResidenceTime */
double PDQ_GetQueueLength(char *device, char *work, int should_be_class) { char *p = "PDQ_GetQueueLength()"; extern char s1[]; double q, x; int c, k; c = getjob_index(work); x = PDQ_GetThruput(should_be_class, work); for (k = 0; k < nodes; k++) { if (strcmp(device, node[k].devname) == 0) { q = node[k].resit[c] * x; return (q); } } sprintf(s1, "Unknown device %s", device); errmsg(p, s1); g_debug("PDQ_GetQueueLength - Bad double return"); return -1.0; } /* PDQ_GetQueueLength */
double PDQ_GetThruMax(int should_be_class, char *wname) { char *p = "PDQ_GetThruMax()"; double x; int job_index = getjob_index(wname); if ((job_index >= 0) && (job_index < streams)) { switch (should_be_class) { case TERM: x = job[job_index].term->sys->maxTP; break; case BATCH: x = job[job_index].batch->sys->maxTP; break; case TRANS: x = job[job_index].trans->sys->maxTP; break; default: errmsg(p, "Unknown should_be_class"); break; } } else { fprintf(stderr, "[PDQ_GetThruMax] Invalid job index (%d)\n", job_index); exit(99); } return (x); } /* PDQ_GetThruMax */
double PDQ_GetLoadOpt(int should_be_class, char *wname) { char *p = "PDQ_GetLoadOpt()"; // Edited by NJG on Tuesday, August 18, 2015 // Initialize vars to suppress compiler warnings double Dmax = 0.0; double Dsum = 0.0; double Nopt = 0.0; double Z = 0.0; int job_index = getjob_index(wname); // Added by NJG on Wednesday, August 19, 2015 if (!streams) PRINTF("PDQ_GetLoadOpt warning: No PDQ workload defined.\n"); if (!nodes) PRINTF("PDQ_GetLoadOpt warning: No PDQ nodes defined.\n"); if (!demands) PRINTF("PDQ_GetLoadOpt warning: No PDQ service demands defined.\n"); if ((job_index >= 0) && (job_index < streams)) { switch (should_be_class) { case TERM: Dsum = job[job_index].term->sys->minRT; Dmax = 1.0 / job[job_index].term->sys->maxTP; Z = job[job_index].term->think; break; case BATCH: Dsum = job[job_index].batch->sys->minRT; Dmax = 1.0 / job[job_index].batch->sys->maxTP; Z = 0.0; break; case TRANS: errmsg(p, "Cannot calculate max Load for TRANS class"); break; default: errmsg(p, "Unknown should_be_class"); break; } } else { #ifndef __R_PDQ fprintf(stderr, "[PDQ_GetLoadOpt] Invalid job index (%d)\n", job_index); exit(99); #else // REprintf("[PDQ_GetLoadOpt] Invalid job index (%d)\n", job_index); error("[PDQ_GetLoadOpt] Invalid job index (%d)\n", job_index); #endif } Nopt = (Dsum + Z) / Dmax; // Removed Tuesday, August 18, 2015 //return (floor(Nopt)); /* return lower bound as integral value */ // Want theoretical value, not rounded down 'practical' value. // If Nopt < 1 then floor produces zero !!! return (Nopt); } /* PDQ_GetLoadOpt */
double PDQ_GetUtilization(char *device, char *work, int should_be_class) { char *p = "PDQ_GetUtilization()"; extern char s1[]; // Initialize vars to suppress compiler warnings double x = 0.0; double u = 0.0; int c = 0; int k = 0; int m = 0; // Added by NJG on Wednesday, August 19, 2015 if (!streams) PRINTF("PDQ_GetUtilization warning: No PDQ workload defined.\n"); if (!nodes) PRINTF("PDQ_GetUtilization warning: No PDQ nodes defined.\n"); if (!demands) PRINTF("PDQ_GetUtilization warning: No PDQ service demands defined.\n"); // g_debug("PDQ_GetUtilization\n"); // g_debugf("job[%d]\n", job); // g_debugf("work[%s]\n", work); // g_debugf("class[%d]\n", should_be_class); if (job) { // g_debugf("work[%s]\n", work); c = getjob_index(work); x = PDQ_GetThruput(should_be_class, work); for (k = 0; k < nodes; k++) { if (strcmp(device, node[k].devname) == 0) { // X is total arrival rate for MSQ u = node[k].demand[c] * x; // Updated by NJG on Dec 29, 2018 with new NODE_TYPEs in PDQ_Lib.h // Edited by NJG on September 10, 2009 // Divide by m to calculate per-server utilization if (node[k].devtype == MSO) { m = node[k].servers; u = u / m; } return (u); } } sprintf(s1, "Unknown device %s", device); errmsg(p, s1); } g_debug("PDQ_GetUtiliation: Failed to find utilization\n"); /* # b. why is there no return value? */ return 0.0; } /* PDQ_GetUtilization */
void PDQ_SetVisits_p(char *nodename, char *workname, double *visits, double *service) { extern NODE_TYPE *node; extern int demand_ext; extern int PDQ_DEBUG; char *p = "PDQ_SetVisits()"; if (PDQ_DEBUG) { PRINTF("nodename : %s workname : %s visits : %f service : %f\n", nodename, workname, *visits, *service); } if (demand_ext == VOID || demand_ext == VISITS) { node[getnode_index(nodename)].visits[getjob_index(workname)] = *visits; node[getnode_index(nodename)].service[getjob_index(workname)] = *service; node[getnode_index(nodename)].demand[getjob_index(workname)] = (*visits) * (*service); demand_ext = VISITS; } else errmsg(p, "Extension conflict"); } // PDQ_SetVisits
double PDQ_GetUtilization(char *device, char *work, int should_be_class) { char *p = "PDQ_GetUtilization()"; extern char s1[]; double x, u; int c, k, m; // g_debug("PDQ_GetUtilization\n"); // g_debugf("job[%d]\n", job); // g_debugf("work[%s]\n", work); // g_debugf("class[%d]\n", should_be_class); if (job) { // g_debugf("work[%s]\n", work); c = getjob_index(work); x = PDQ_GetThruput(should_be_class, work); for (k = 0; k < nodes; k++) { if (strcmp(device, node[k].devname) == 0) { // X is total arrival rate for MSQ u = node[k].demand[c] * x; // Edited by NJG on Thursday, September 10, 2009 // Calculate per-server utilization; divide by m if (node[k].sched == MSQ) { m = node[k].devtype; u = u/m; } return (u); } } sprintf(s1, "Unknown device %s", device); errmsg(p, s1); } g_debug("PDQ_GetUtiliation: Failed to find utilization\n"); /* # b. why is there no return value? */ return 0.0; } /* PDQ_GetUtilization */
double PDQ_GetResponse(int should_be_class, char *wname) { char *p = "PDQ_GetResponse()"; double r = 0.0; int job_index = getjob_index(wname); // Added by NJG on Wednesday, August 19, 2015 if (!streams) PRINTF("PDQ_GetResponse warning: No PDQ workload defined.\n"); if (!nodes) PRINTF("PDQ_GetResponse warning: No PDQ nodes defined.\n"); if (!demands) PRINTF("PDQ_GetResponse warning: No PDQ service demands defined.\n"); if ((job_index >= 0) && (job_index < streams)) { switch (should_be_class) { case TERM: r = job[job_index].term->sys->response; break; case BATCH: r = job[job_index].batch->sys->response; break; case TRANS: r = job[job_index].trans->sys->response; break; default: errmsg(p, "Unknown should_be_class"); break; } } else { #ifndef __R_PDQ fprintf(stderr, "[PDQ_GetResponse] Invalid job index (%d)\n", job_index); exit(99); #else // REprintf("[PDQ_GetResponse] Invalid job index (%d)\n", job_index); error("[PDQ_GetResponse] Invalid job index (%d)\n", job_index); #endif } return (r); } /* PDQ_GetResponse */
double PDQ_GetLoadOpt(int should_be_class, char *wname) { char *p = "PDQ_GetLoadOpt()"; double Dmax, Dsum; double Nopt, Z; int job_index = getjob_index(wname); if ((job_index >= 0) && (job_index < streams)) { switch (should_be_class) { case TERM: Dsum = job[job_index].term->sys->minRT; Dmax = 1.0 / job[job_index].term->sys->maxTP; Z = job[job_index].term->think; break; case BATCH: Dsum = job[job_index].batch->sys->minRT; Dmax = 1.0 / job[job_index].batch->sys->maxTP; Z = 0.0; break; case TRANS: errmsg(p, "Cannot calculate max Load for TRANS class"); break; default: errmsg(p, "Unknown should_be_class"); break; } } else { fprintf(stderr, "[PDQ_GetThruMax] Invalid job index (%d)\n", job_index); exit(99); } Nopt = (Dsum + Z) / Dmax; return (floor(Nopt)); /* return lower bound as integral value */ } /* PDQ_GetLoadOpt */
double PDQ_GetResidenceTime(char *device, char *work, int should_be_class) { char *p = "PDQ_GetResidenceTime()"; extern char s1[]; double r; int c, k; c = getjob_index(work); for (k = 0; k < nodes; k++) { if (strcmp(device, node[k].devname) == 0) { r = node[k].resit[c]; return (r); } } sprintf(s1, "Unknown device %s", device); errmsg(p, s1); g_debug("PDQ_GetResidenceTime: Returning bad double\n"); return -1.0; } /* PDQ_GetResidenceTime */
void PDQ_SetDemand_p(char *nodename, char *workname, double *time) { char *p = "PDQ_SetDemand()"; extern NODE_TYPE *node; extern int nodes; extern int streams; extern int demands; // from PDQ_Globals.h extern int demand_ext; extern int PDQ_DEBUG; int node_index; int job_index; FILE *out_fd; demands = 1; // count is non-zero since SetDemand now called if (PDQ_DEBUG) { debug(p, "Entering"); out_fd = fopen("PDQ.out", "a"); fprintf(out_fd, "nodename : %s workname : %s time : %f\n", nodename, workname, *time); //PJP This should really be fclose // close(out_fd); fclose(out_fd); } /* that demand type is being used consistently per model */ if (demand_ext == VOID || demand_ext == DEMAND) { node_index = getnode_index(nodename); job_index = getjob_index(workname); #ifndef __R_PDQ if (!((node_index >=0) && (node_index <= nodes))) { fprintf(stderr, "Illegal node index value %d\n", node_index); exit(1); } if (!((job_index >=0) && (job_index <= streams))) { fprintf(stderr, "Illegal job index value %d\n", job_index); exit(1); } #else if (!((node_index >=0) && (node_index <= nodes))) { // REprintf("Illegal node index value %d\n", node_index); error("Illegal node index value %d\n", node_index); } if (!((job_index >=0) && (job_index <= streams))) { // REprintf("Illegal node index value %d\n", node_index); error("Illegal node index value %d\n", node_index); } #endif node[node_index].demand[job_index] = *time; demand_ext = DEMAND; } else { errmsg(p, "Extension conflict"); } if (PDQ_DEBUG) { debug(p, "Exiting"); } } // PDQ_SetDemand
int main() { extern JOB_TYPE *job; extern double getjob_pop(); extern int getjob_index(); extern double PDQ_GetResponse(); extern double PDQ_GetThruput(); extern double PDQ_GetUtilization(); /**************************** * Model specific variables * ****************************/ int noNodes; int noStreams; int pop, servers = 2; int s, w; #define STRESS 0 #define HOMEPG 1 static char *work[] = { "stress", "homepg" }; static double time[] = { 0.0044, /* stress */ 0.0300 /* homepg */ }; static char *slave[] = { "slave0", "slave1", "slave2", "slave3", "slave4", "slave5", "slave6", "slave7", "slave8", "slave9", "slave10", "slave11", "slave12", "slave13", "slave14", "slave15" }; #define PREFORK w = HOMEPG; #ifdef PREFORK printf("Pre-Fork Model under \"%s\" Load (m = %d)\n", w == STRESS ? work[STRESS] : work[HOMEPG], servers); #else printf("Forking Model under \"%s\" Load \n", w == STRESS ? work[STRESS] : work[HOMEPG]); #endif printf("\n N X R\n"); for (pop = 1; pop <= 10; pop++) { PDQ_Init("HTTPd_Server"); noStreams = PDQ_CreateClosed(work[w], TERM, 1.0 * pop, 0.0); noNodes = PDQ_CreateNode("master", CEN, FCFS); #ifdef PREFORK for (s = 0; s < servers; s++) { noNodes = PDQ_CreateNode(slave[s], CEN, FCFS); } PDQ_SetDemand("master", work[w], 0.0109); for (s = 0; s < servers; s++) { PDQ_SetDemand(slave[s], work[w], time[w] / servers); } #else /* FORKING */ noNodes = PDQ_CreateNode("forks", CEN, ISRV); PDQ_SetDemand("master", work[w], 0.0165); PDQ_SetDemand("forks", work[w], time[w]); #endif PDQ_Solve(EXACT); printf("%5.2f %8.4f %8.4f\n", getjob_pop(getjob_index(work[w])), PDQ_GetThruput(TERM, work[w]), PDQ_GetResponse(TERM, work[w])); } return(0); } // main