Parent Directory
|
Revision Log
Package all media, etc. needed for Public demo system into one tree
1 /* 2 * This program is free software; you can redistribute it and/or modify 3 * it under the terms of the GNU General Public License as published by 4 * the Free Software Foundation; either version 2 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, 8 * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * GNU General Public License for more details. 11 * 12 * You should have received a copy of the GNU General Public License 13 * along with this program; if not, write to the Free Software 14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 15 * 16 * Authors : Benjamin GAUTHIER - 24 Mar 2004 17 * Joseph BANINO 18 * Olivier JACQUES 19 * Richard GAYRAUD 20 * From Hewlett Packard Company. 21 * Wolfgang Beck 22 * 23 */ 24 25 #include <iostream> 26 #include <fstream> 27 #include <iomanip> 28 29 #include "sipp.hpp" 30 #include "scenario.hpp" 31 #include "screen.hpp" 32 #ifdef HAVE_GSL 33 #include <gsl/gsl_rng.h> 34 #include <gsl/gsl_randist.h> 35 #include <gsl/gsl_cdf.h> 36 #endif 37 38 /* 39 ** Local definitions (macros) 40 */ 41 42 /* 43 ** Warning! All DISPLAY_ macros must be called where f FILE is 44 ** defined. This is to allow printing to stdout or a file. 45 */ 46 #define DISPLAY_LINE()\ 47 fprintf(f," ------------------------------------------------------------------------------ \r\n") 48 #define DISPLAY_DLINE()\ 49 fprintf(f,"================================================================================\r\n") 50 #define DISPLAY_CROSS_LINE()\ 51 fprintf(f,"-------------------------+---------------------------+--------------------------\r\n") 52 53 #define DISPLAY_HEADER()\ 54 fprintf(f," Counter Name | Periodic value | Cumulative value\r\n") 55 #define DISPLAY_TXT_COL(T1, V1, V2)\ 56 fprintf(f," %-22.22s | %-25.25s |", T1, V1); fprintf(f," %-24.24s \r\n", V2) 57 #define DISPLAY_VAL_RATEF_COL(T1, V1, V2)\ 58 fprintf(f," %-22.22s | %8.3f cps | %8.3f cps \r\n", T1, V1, V2) 59 #define DISPLAY_2VAL(T1, V1, V2)\ 60 fprintf(f," %-22.22s | %8llu | %8llu \r\n", T1, V1, V2) 61 #define DISPLAY_CUMUL(T1, V1)\ 62 fprintf(f," %-22.22s | | %8llu \r\n", T1, V1) 63 #define DISPLAY_PERIO(T1, V1)\ 64 fprintf(f," %-22.22s | %8llu | \r\n", T1, V1) 65 #define DISPLAY_VALF(T1, V1)\ 66 fprintf(f," %-22.22s | %8.3f ms \r\n", T1, V1) 67 #define DISPLAY_VAL_RATEF(T1, V1)\ 68 fprintf(f," %-22.22s | %8.3f cps \r\n", T1, V1) 69 #define DISPLAY_VAL_RATE(T1, V1)\ 70 fprintf(f," %-22.22s | %8d cps \r\n", T1, V1) 71 #define DISPLAY_VAL(T1, V1)\ 72 fprintf(f," %-22.22s : %8d \r\n", T1, V1) 73 #define DISPLAY_2VALF(T1, V1, T2, V2)\ 74 fprintf(f," %-22.22s : %8.2f | %-7.7s : %8.2f \r\n", T1, V1, T2, V2) 75 #define DISPLAY_3VAL(T1, V1, T2, V2, T3, V3)\ 76 fprintf(f," %-22.22s : %8d | %-7.7s : %8d | %-12.12s : %5d \r\n", T1, V1, T2, V2, T3, V3) 77 #define DISPLAY_3VALF(T1, V1, T2, V2, T3, V3)\ 78 fprintf(f," %-22.22s : %8.3f | %-7.7s : %8.3f | %-12.12s : %5.1f \r\n", T1, V1, T2, V2, T3, V3) 79 #define DISPLAY_TXT(T1, V1)\ 80 fprintf(f," %-22.22s | %-52.52s \r\n", T1, V1) 81 #define DISPLAY_INFO(T1)\ 82 fprintf(f," %-77.77s \r\n", T1) 83 #define DISPLAY_REPART(T1, T2, V1)\ 84 fprintf(f," %8d ms <= n < %8d ms : %10d %-29.29s \r\n", T1, T2, V1, "") 85 #define DISPLAY_LAST_REPART(T1, V1)\ 86 fprintf(f," %14.14s n >= %8d ms : %10d %-29.29s \r\n", "", T1, V1, "") 87 88 #define RESET_COUNTERS(PT)\ 89 memset (PT, 0, CStat::E_NB_COUNTER * sizeof(unsigned long long)) 90 91 #define RESET_PD_COUNTERS(PT) \ 92 { \ 93 int i; \ 94 for (i=CStat::CPT_PD_IncomingCallCreated; \ 95 i<=CStat::CPT_PD_AutoAnswered; \ 96 i++) \ 97 PT[i] = (unsigned long) 0; \ 98 } 99 100 #define RESET_PL_COUNTERS(PT) \ 101 { \ 102 int i; \ 103 for (i=CStat::CPT_PL_IncomingCallCreated; \ 104 i<=CStat::CPT_PL_AutoAnswered; \ 105 i++) \ 106 PT[i] = (unsigned long) 0; \ 107 } 108 109 /* 110 __________________________________________________________________________ 111 112 C L A S S CS t a t 113 __________________________________________________________________________ 114 */ 115 116 CStat* CStat::instance() 117 { 118 if ( M_instance == NULL ) M_instance = new CStat(); 119 return M_instance; 120 } 121 122 123 void CStat::close () 124 { 125 int i; 126 127 for (i = 0; i < MAX_RTD_INFO_LENGTH; i++) { 128 if (M_ResponseTimeRepartition[i] != NULL) { 129 delete [] M_ResponseTimeRepartition[i]; 130 } 131 } 132 133 if (M_CallLengthRepartition != NULL) 134 delete [] M_CallLengthRepartition; 135 136 if(M_outputStream != NULL) 137 { 138 M_outputStream->close(); 139 delete M_outputStream; 140 } 141 142 if(M_fileName != NULL) 143 delete [] M_fileName; 144 145 if(M_outputStreamRtt != NULL) 146 { 147 M_outputStreamRtt->close(); 148 delete M_outputStreamRtt; 149 } 150 if(M_fileNameRtt != NULL) 151 delete [] M_fileNameRtt; 152 153 154 if(M_dumpRespTime != NULL) 155 delete [] M_dumpRespTime ; 156 157 158 M_SizeOfResponseTimeRepartition = 0; 159 M_SizeOfCallLengthRepartition = 0; 160 M_CallLengthRepartition = NULL; 161 M_fileName = NULL; 162 M_outputStream = NULL; 163 164 M_outputStreamRtt = NULL; 165 M_fileNameRtt = NULL; 166 M_dumpRespTime = NULL; 167 168 for (i = 0; i < MAX_RTD_INFO_LENGTH; i++) { 169 M_ResponseTimeRepartition[i] = NULL; 170 } 171 172 // On last position 173 if (M_instance != NULL) 174 delete M_instance; 175 M_instance = NULL; 176 } 177 178 179 int CStat::init () 180 { 181 // reset of all counter 182 RESET_COUNTERS(M_counters); 183 GET_TIME (&M_startTime); 184 memcpy (&M_pdStartTime, &M_startTime, sizeof (struct timeval)); 185 memcpy (&M_plStartTime, &M_startTime, sizeof (struct timeval)); 186 M_outputStream = NULL; 187 M_headerAlreadyDisplayed = false; 188 189 M_outputStreamRtt = NULL; 190 M_headerAlreadyDisplayedRtt = false; 191 192 return(1); 193 } 194 195 196 int CStat::isWellFormed(char * P_listeStr, 197 int * nombre) 198 { 199 char * ptr = P_listeStr; 200 int sizeOf; 201 bool isANumber; 202 203 (*nombre) = 0; 204 sizeOf = strlen(P_listeStr); 205 // getting the number 206 if(sizeOf > 0) 207 { 208 // is the string well formed ? [0-9] [,] 209 isANumber = false; 210 for(int i=0; i<=sizeOf; i++) 211 { 212 switch(ptr[i]) 213 { 214 case ',': 215 if(isANumber == false) 216 { 217 return(0); 218 } 219 else 220 { 221 (*nombre)++; 222 } 223 isANumber = false; 224 break; 225 case '0': 226 case '1': 227 case '2': 228 case '3': 229 case '4': 230 case '5': 231 case '6': 232 case '7': 233 case '8': 234 case '9': 235 isANumber = true; 236 break; 237 case '\t': 238 case ' ' : 239 break; 240 case '\0': 241 if(isANumber == false) 242 { 243 return(0); 244 } 245 else 246 { 247 (*nombre)++; 248 } 249 break; 250 default: 251 return(0); 252 } 253 } // enf for 254 } 255 return(1); 256 } 257 258 259 int CStat::createIntegerTable(char * P_listeStr, 260 unsigned int ** listeInteger, 261 int * sizeOfList) 262 { 263 int nb=0; 264 char * ptr = P_listeStr; 265 char * ptr_prev = P_listeStr; 266 unsigned int current_int; 267 268 if(isWellFormed(P_listeStr, sizeOfList) == 1) 269 { 270 (*listeInteger) = new unsigned int[(*sizeOfList)]; 271 while((*ptr) != ('\0')) 272 { 273 if((*ptr) == ',') 274 { 275 sscanf(ptr_prev, "%u", ¤t_int); 276 if (nb<(*sizeOfList)) 277 (*listeInteger)[nb] = current_int; 278 nb++; 279 ptr_prev = ptr+1; 280 } 281 ptr++; 282 } 283 // on lit le dernier 284 sscanf(ptr_prev, "%u", ¤t_int); 285 if (nb<(*sizeOfList)) 286 (*listeInteger)[nb] = current_int; 287 nb++; 288 return(1); 289 } 290 return(0); 291 } 292 293 294 void CStat::setFileName(char * P_name, char * P_extension) 295 { 296 int sizeOf, sizeOfExtension; 297 298 if(P_name != NULL) 299 { 300 // +6 for PID 301 sizeOf = strlen(P_name) + 6; 302 if(sizeOf > 0) 303 { 304 if(P_extension != NULL) 305 { 306 sizeOfExtension = strlen(P_extension); 307 if(sizeOfExtension > 0) 308 { 309 if(M_fileName != NULL) 310 delete [] M_fileName; 311 sizeOf += sizeOfExtension; 312 M_fileName = new char[MAX_PATH]; 313 sprintf(M_fileName, "%s_%d_", P_name, getpid()); 314 strcat(M_fileName, P_extension); 315 } 316 else 317 { 318 if(M_fileName != NULL) 319 delete [] M_fileName; 320 sizeOf += strlen(DEFAULT_EXTENSION); 321 M_fileName = new char[MAX_PATH]; 322 sprintf(M_fileName, "%s_%d_", P_name, getpid()); 323 strcat(M_fileName, DEFAULT_EXTENSION); 324 } 325 } 326 else 327 { 328 if(M_fileName != NULL) 329 delete [] M_fileName; 330 sizeOf += strlen(DEFAULT_EXTENSION); 331 M_fileName = new char[MAX_PATH]; 332 sprintf(M_fileName, "%s_%d_", P_name, getpid()); 333 strcat(M_fileName, DEFAULT_EXTENSION); 334 } 335 } 336 else 337 { 338 cerr << "new file name length is null - " 339 << "keeping the default filename : " 340 << DEFAULT_FILE_NAME << endl; 341 } 342 } 343 else 344 { 345 cerr << "new file name is NULL ! - keeping the default filename : " 346 << DEFAULT_FILE_NAME << endl; 347 } 348 } 349 350 351 void CStat::setFileName(char * P_name) 352 { 353 int sizeOf; 354 355 if(P_name != NULL) 356 { 357 sizeOf = strlen(P_name); 358 if(sizeOf > 0) 359 { 360 if(M_fileName != NULL) 361 delete [] M_fileName; 362 M_fileName = new char[sizeOf+1]; 363 strcpy(M_fileName, P_name); 364 } 365 else 366 { 367 cerr << "new file name length is null - " 368 "keeping the default filename : " 369 << DEFAULT_FILE_NAME << endl; 370 } 371 } 372 else 373 { 374 cerr << "new file name is NULL ! - keeping the default filename : " 375 << DEFAULT_FILE_NAME << endl; 376 } 377 } 378 379 380 void CStat::initRtt(char * P_name, char * P_extension, 381 unsigned long P_report_freq_dumpRtt) { 382 int sizeOf, sizeOfExtension; 383 384 if(P_name != NULL) { 385 sizeOf = strlen(P_name) ; 386 if(sizeOf > 0) { 387 // 4 for '_rtt' and 6 for pid 388 sizeOf += 10 ; 389 sizeOfExtension = strlen(P_extension); 390 if(M_fileNameRtt != NULL) 391 delete [] M_fileNameRtt; 392 sizeOf += sizeOfExtension; 393 M_fileNameRtt = new char[sizeOf+1]; 394 sprintf (M_fileNameRtt, "%s_%d_rtt%s", P_name, getpid(),P_extension); 395 } else { 396 cerr << "new file name length is null - " 397 << "keeping the default filename : " 398 << DEFAULT_FILE_NAME << endl; 399 } 400 } else { 401 cerr << "new file name is NULL ! - keeping the default filename : " 402 << DEFAULT_FILE_NAME << endl; 403 } 404 405 // initiate the table dump response time 406 M_report_freq_dumpRtt = P_report_freq_dumpRtt ; 407 408 M_dumpRespTime = new T_value_rtt [P_report_freq_dumpRtt] ; 409 410 if ( M_dumpRespTime == NULL ) { 411 cerr << "Memory allocation failure" << endl; 412 exit(EXIT_FATAL_ERROR); 413 } 414 415 for (unsigned L_i = 0 ; L_i < P_report_freq_dumpRtt; L_i ++) { 416 M_dumpRespTime[L_i].date = 0.0; 417 M_dumpRespTime[L_i].rtd_no = 0; 418 M_dumpRespTime[L_i].rtt = 0.0; 419 } 420 } 421 422 void CStat::setRepartitionCallLength(char * P_listeStr) 423 { 424 unsigned int * listeInteger; 425 int sizeOfListe; 426 427 if(createIntegerTable(P_listeStr, &listeInteger, &sizeOfListe) == 1) { 428 initRepartition(listeInteger, 429 sizeOfListe, 430 &M_CallLengthRepartition, 431 &M_SizeOfCallLengthRepartition); 432 } else { 433 ERROR_P1("Could not create table for call length repartition '%s'\n", P_listeStr); 434 } 435 delete [] listeInteger; 436 listeInteger = NULL; 437 } 438 439 void CStat::setRepartitionResponseTime (char * P_listeStr) 440 { 441 unsigned int * listeInteger; 442 int sizeOfListe; 443 int i; 444 445 for (i = 0; i < MAX_RTD_INFO_LENGTH; i++) { 446 if(createIntegerTable(P_listeStr, &listeInteger, &sizeOfListe) == 1) { 447 initRepartition(listeInteger, 448 sizeOfListe, 449 &M_ResponseTimeRepartition[i], 450 &M_SizeOfResponseTimeRepartition); 451 } else { 452 ERROR_P1("Could not create table for response time repartition '%s'\n", P_listeStr); 453 } 454 } 455 delete [] listeInteger; 456 listeInteger = NULL; 457 } 458 459 460 void CStat::setRepartitionCallLength(unsigned int* repartition, 461 int nombre) 462 { 463 initRepartition(repartition, 464 nombre, 465 &M_CallLengthRepartition, 466 &M_SizeOfCallLengthRepartition); 467 } 468 469 void CStat::setRepartitionResponseTime(unsigned int* repartition, 470 int nombre) 471 { 472 for (int i = 0; i < MAX_RTD_INFO_LENGTH; i++) { 473 initRepartition(repartition, 474 nombre, 475 &M_ResponseTimeRepartition[i], 476 &M_SizeOfResponseTimeRepartition); 477 } 478 } 479 480 481 void CStat::initRepartition(unsigned int* repartition, 482 int nombre, 483 T_dynamicalRepartition ** tabRepartition, 484 int* tabNb) 485 { 486 bool sortDone; 487 int i; 488 unsigned int swap; 489 490 if((nombre <= 0) || (repartition == NULL) ) 491 { 492 (*tabNb) = 0; 493 (*tabRepartition) = NULL; 494 return; 495 } 496 497 (*tabNb) = nombre + 1; 498 (*tabRepartition) = new T_dynamicalRepartition[(*tabNb)]; 499 500 // copying the repartition table in the local table 501 for(i=0; i<nombre; i++) 502 { 503 (*tabRepartition)[i].borderMax = repartition[i]; 504 (*tabRepartition)[i].nbInThisBorder = 0; 505 } 506 507 // sorting the repartition table 508 sortDone = false; 509 while(!sortDone) 510 { 511 sortDone = true; 512 for(i=0; i<(nombre-1); i++) 513 { 514 if((*tabRepartition)[i].borderMax > (*tabRepartition)[i+1].borderMax) 515 { 516 // swapping this two value and setting sortDone to false 517 swap = (*tabRepartition)[i].borderMax; 518 (*tabRepartition)[i].borderMax = 519 (*tabRepartition)[i+1].borderMax; 520 (*tabRepartition)[i+1].borderMax = swap; 521 sortDone = false; 522 } 523 } 524 } 525 // setting the range for max <= value < infinity 526 (*tabRepartition)[nombre].borderMax = 527 (*tabRepartition)[nombre-1].borderMax; 528 (*tabRepartition)[nombre].nbInThisBorder = 0; 529 } 530 531 532 int CStat::computeStat (E_Action P_action) 533 { 534 switch (P_action) 535 { 536 case E_CREATE_OUTGOING_CALL : 537 M_counters [CPT_C_OutgoingCallCreated]++; 538 M_counters [CPT_PD_OutgoingCallCreated]++; 539 M_counters [CPT_PL_OutgoingCallCreated]++; 540 M_counters [CPT_C_CurrentCall]++; 541 break; 542 543 case E_CREATE_INCOMING_CALL : 544 M_counters [CPT_C_IncomingCallCreated]++; 545 M_counters [CPT_PD_IncomingCallCreated]++; 546 M_counters [CPT_PL_IncomingCallCreated]++; 547 M_counters [CPT_C_CurrentCall]++; 548 break; 549 550 case E_CALL_FAILED : 551 M_counters [CPT_C_FailedCall]++; 552 M_counters [CPT_PD_FailedCall]++; 553 M_counters [CPT_PL_FailedCall]++; 554 M_counters [CPT_C_CurrentCall]--; 555 break; 556 557 case E_CALL_SUCCESSFULLY_ENDED : 558 M_counters [CPT_C_SuccessfulCall]++; 559 M_counters [CPT_PD_SuccessfulCall]++; 560 M_counters [CPT_PL_SuccessfulCall]++; 561 M_counters [CPT_C_CurrentCall]--; 562 break; 563 564 case E_FAILED_CANNOT_SEND_MSG : 565 M_counters [CPT_C_FailedCallCannotSendMessage]++; 566 M_counters [CPT_PD_FailedCallCannotSendMessage]++; 567 M_counters [CPT_PL_FailedCallCannotSendMessage]++; 568 break; 569 570 case E_FAILED_MAX_UDP_RETRANS : 571 M_counters [CPT_C_FailedCallMaxUdpRetrans]++; 572 M_counters [CPT_PD_FailedCallMaxUdpRetrans]++; 573 M_counters [CPT_PL_FailedCallMaxUdpRetrans]++; 574 break; 575 576 case E_FAILED_UNEXPECTED_MSG : 577 M_counters [CPT_C_FailedCallUnexpectedMessage]++; 578 M_counters [CPT_PD_FailedCallUnexpectedMessage]++; 579 M_counters [CPT_PL_FailedCallUnexpectedMessage]++; 580 break; 581 582 case E_FAILED_CALL_REJECTED : 583 M_counters [CPT_C_FailedCallCallRejected]++; 584 M_counters [CPT_PD_FailedCallCallRejected]++; 585 M_counters [CPT_PL_FailedCallCallRejected]++; 586 break; 587 588 case E_FAILED_CMD_NOT_SENT : 589 M_counters [CPT_C_FailedCallCmdNotSent]++; 590 M_counters [CPT_PD_FailedCallCmdNotSent]++; 591 M_counters [CPT_PL_FailedCallCmdNotSent]++; 592 break; 593 594 case E_FAILED_REGEXP_DOESNT_MATCH : 595 M_counters [CPT_C_FailedCallRegexpDoesntMatch]++; 596 M_counters [CPT_PD_FailedCallRegexpDoesntMatch]++; 597 M_counters [CPT_PL_FailedCallRegexpDoesntMatch]++; 598 break; 599 600 case E_FAILED_REGEXP_HDR_NOT_FOUND : 601 M_counters [CPT_C_FailedCallRegexpHdrNotFound]++; 602 M_counters [CPT_PD_FailedCallRegexpHdrNotFound]++; 603 M_counters [CPT_PL_FailedCallRegexpHdrNotFound]++; 604 break; 605 606 case E_FAILED_OUTBOUND_CONGESTION : 607 M_counters [CPT_C_FailedOutboundCongestion]++; 608 M_counters [CPT_PD_FailedOutboundCongestion]++; 609 M_counters [CPT_PL_FailedOutboundCongestion]++; 610 break; 611 612 case E_FAILED_TIMEOUT_ON_RECV : 613 M_counters [CPT_C_FailedTimeoutOnRecv]++; 614 M_counters [CPT_PD_FailedTimeoutOnRecv]++; 615 M_counters [CPT_PL_FailedTimeoutOnRecv]++; 616 break; 617 618 case E_FAILED_TIMEOUT_ON_SEND : 619 M_counters [CPT_C_FailedTimeoutOnSend]++; 620 M_counters [CPT_PD_FailedTimeoutOnSend]++; 621 M_counters [CPT_PL_FailedTimeoutOnSend]++; 622 break; 623 624 case E_OUT_OF_CALL_MSGS : 625 M_counters [CPT_C_OutOfCallMsgs]++; 626 M_counters [CPT_PD_OutOfCallMsgs]++; 627 M_counters [CPT_PL_OutOfCallMsgs]++; 628 break; 629 630 case E_RETRANSMISSION : 631 M_counters [CPT_C_Retransmissions]++; 632 M_counters [CPT_PD_Retransmissions]++; 633 M_counters [CPT_PL_Retransmissions]++; 634 break; 635 636 637 case E_AUTO_ANSWERED : 638 // Let's count the automatic answered calls 639 M_counters [CPT_C_AutoAnswered]++; 640 M_counters [CPT_PD_AutoAnswered]++; 641 M_counters [CPT_PL_AutoAnswered]++; 642 break; 643 644 case E_RESET_PD_COUNTERS : 645 //DEBUG (C_Debug::E_LEVEL_4, "ENTER CASE", "%s", 646 // "CStat::computeStat : RESET_PD_COUNTERS"); 647 RESET_PD_COUNTERS (M_counters); 648 GET_TIME (&M_pdStartTime); 649 break; 650 651 case E_RESET_PL_COUNTERS : 652 //DEBUG (C_Debug::E_LEVEL_4, "ENTER CASE", "%s", 653 // "C_Stat::computeStat : RESET_PL_COUNTERS"); 654 RESET_PL_COUNTERS (M_counters); 655 GET_TIME (&M_plStartTime); 656 break; 657 658 default : 659 ERROR_P1("CStat::ComputeStat() - Unrecognized Action %d\n", P_action); 660 return (-1); 661 } /* end switch */ 662 return (0); 663 } 664 665 void CStat::computeRtt (unsigned long long P_start_time, unsigned long long P_stop_time, int which) { 666 M_dumpRespTime[M_counterDumpRespTime].date = (double)P_stop_time / (double)1000; 667 M_dumpRespTime[M_counterDumpRespTime].rtd_no = which; 668 M_dumpRespTime[M_counterDumpRespTime].rtt = 669 ((double)(P_stop_time - P_start_time)) / (double)1000; 670 M_counterDumpRespTime++ ; 671 672 if (M_counterDumpRespTime > (M_report_freq_dumpRtt - 1)) { 673 dumpDataRtt () ; 674 } 675 } 676 677 unsigned long long CStat::get_current_counter_call (){ 678 return M_counters[CPT_C_CurrentCall]; 679 } 680 681 unsigned long long CStat::GetStat (E_CounterName P_counter) 682 { 683 return M_counters [P_counter]; 684 } 685 686 /* Use the short form standard deviation formula given the sum of the squares 687 * and the sum. */ 688 double CStat::computeStdev(E_CounterName P_SumCounter, 689 E_CounterName P_NbOfCallUsed, 690 E_CounterName P_Squares) { 691 if (M_counters[P_NbOfCallUsed] == 0) 692 return 0.0; 693 694 double numerator = ((double)(M_counters[P_NbOfCallUsed]) * (double)(M_counters[P_Squares])) - ((double)(M_counters[P_SumCounter] * M_counters[P_SumCounter])); 695 double denominator = (double)(M_counters[P_NbOfCallUsed]) * (((double)(M_counters[P_NbOfCallUsed])) - 1.0); 696 697 return sqrt(numerator/denominator); 698 } 699 700 double CStat::computeMean(E_CounterName P_SumCounter, 701 E_CounterName P_NbOfCallUsed) { 702 if (M_counters[P_NbOfCallUsed] == 0) 703 return 0.0; 704 return ((double)(M_counters[P_SumCounter]) / (double)(M_counters[P_NbOfCallUsed])); 705 } 706 707 void CStat::updateAverageCounter(E_CounterName P_SumCounter, 708 E_CounterName P_NbOfCallUsed, 709 E_CounterName P_Squares, 710 unsigned long P_value) 711 { 712 if (M_counters [P_NbOfCallUsed] <= 0) 713 { 714 M_counters [P_NbOfCallUsed] ++; 715 M_counters [P_SumCounter] = P_value; 716 M_counters [P_Squares] = (P_value * P_value); 717 } 718 else 719 { 720 M_counters [P_SumCounter] += P_value; 721 M_counters [P_Squares] += (P_value * P_value); 722 M_counters [P_NbOfCallUsed] ++; 723 } 724 } 725 726 int CStat::computeStat (E_Action P_action, 727 unsigned long P_value) { 728 return computeStat(P_action, P_value, 0); 729 } 730 731 int CStat::computeStat (E_Action P_action, 732 unsigned long P_value, 733 int which) 734 { 735 switch (P_action) 736 { 737 case E_ADD_CALL_DURATION : 738 // Updating Cumulative Counter 739 updateAverageCounter(CPT_C_AverageCallLength_Sum, 740 CPT_C_NbOfCallUsedForAverageCallLength, 741 CPT_C_AverageCallLength_Squares, P_value); 742 updateRepartition(M_CallLengthRepartition, 743 M_SizeOfCallLengthRepartition, P_value); 744 // Updating Periodical Diplayed counter 745 updateAverageCounter(CPT_PD_AverageCallLength_Sum, 746 CPT_PD_NbOfCallUsedForAverageCallLength, 747 CPT_PD_AverageCallLength_Squares, P_value); 748 // Updating Periodical Logging counter 749 updateAverageCounter(CPT_PL_AverageCallLength_Sum, 750 CPT_PL_NbOfCallUsedForAverageCallLength, 751 CPT_PL_AverageCallLength_Squares, P_value); 752 break; 753 754 755 case E_ADD_GENERIC_COUNTER : 756 M_counters [CPT_C_Generic + which] += P_value; 757 M_counters [CPT_PD_Generic + which] += P_value; 758 M_counters [CPT_PL_Generic + which] += P_value; 759 break; 760 761 case E_ADD_RESPONSE_TIME_DURATION : 762 // Updating Cumulative Counter 763 updateAverageCounter((E_CounterName)(CPT_C_AverageResponseTime_Sum + which), 764 (E_CounterName)(CPT_C_NbOfCallUsedForAverageResponseTime + which), 765 (E_CounterName)(CPT_C_AverageResponseTime_Squares + which), P_value); 766 updateRepartition(M_ResponseTimeRepartition[which], 767 M_SizeOfResponseTimeRepartition, P_value); 768 // Updating Periodical Diplayed counter 769 updateAverageCounter((E_CounterName)(CPT_PD_AverageResponseTime_Sum + which), 770 (E_CounterName)(CPT_PD_NbOfCallUsedForAverageResponseTime + which), 771 (E_CounterName)(CPT_PD_AverageResponseTime_Squares + which), P_value); 772 // Updating Periodical Logging counter 773 updateAverageCounter((E_CounterName)(CPT_PL_AverageResponseTime_Sum + which), 774 (E_CounterName)(CPT_PL_NbOfCallUsedForAverageResponseTime + which), 775 (E_CounterName)(CPT_PL_AverageResponseTime_Squares + which), P_value); 776 break; 777 778 default : 779 ERROR_P1("CStat::ComputeStat() - Unrecognized Action %d\n", P_action); 780 return (-1); 781 } /* end switch */ 782 return (0); 783 } 784 785 786 void CStat::updateRepartition(T_dynamicalRepartition* P_tabReport, 787 int P_sizeOfTab, 788 unsigned long P_value) 789 { 790 bool found; 791 int i; 792 793 if(P_tabReport != NULL) 794 { 795 i = P_sizeOfTab-2; 796 found = false; 797 while((found == false) && (i>=1)) 798 { 799 if( (P_value < P_tabReport[i].borderMax) && 800 (P_tabReport[i-1].borderMax <= P_value) ) 801 { 802 found = true; 803 P_tabReport[i].nbInThisBorder ++; 804 } 805 i--; 806 } 807 808 if(!found) 809 { 810 if(P_value < P_tabReport[0].borderMax) 811 { 812 P_tabReport[0].nbInThisBorder ++; 813 } 814 else if(P_value >= P_tabReport[P_sizeOfTab-1].borderMax) 815 { 816 P_tabReport[P_sizeOfTab-1].nbInThisBorder ++; 817 } 818 else 819 { 820 // ERROR !!!! 821 printf("\n ERROR - Unable to sort this Value in " 822 "the repartition table! %lu \n", P_value); 823 } 824 } 825 } 826 } 827 828 829 CStat::CStat () 830 { 831 size_t L_size = 0; 832 L_size += strlen(DEFAULT_FILE_NAME) ; 833 L_size += strlen(DEFAULT_EXTENSION) ; 834 L_size += 1 ; 835 M_fileName = new char[L_size]; 836 strcpy(M_fileName, DEFAULT_FILE_NAME); 837 strcat(M_fileName, DEFAULT_EXTENSION); 838 for (int i = 0; i < MAX_RTD_INFO_LENGTH; i++) { 839 M_ResponseTimeRepartition[i] = NULL; 840 } 841 M_CallLengthRepartition = NULL; 842 M_SizeOfResponseTimeRepartition = 0; 843 M_SizeOfCallLengthRepartition = 0; 844 M_fileNameRtt = NULL; 845 M_time_ref = 0.0 ; 846 M_dumpRespTime = NULL ; 847 M_counterDumpRespTime = 0 ; 848 M_dumpRespTime = NULL; 849 M_fileNameRtt = NULL; 850 851 init(); 852 } 853 854 855 CStat::~CStat () 856 { 857 for (int i = 0; i < MAX_RTD_INFO_LENGTH; i++) { 858 if (M_ResponseTimeRepartition[i] == NULL) 859 continue; 860 delete M_ResponseTimeRepartition[i]; 861 } 862 if (M_CallLengthRepartition != NULL) 863 delete M_CallLengthRepartition; 864 } 865 866 char* CStat::sRepartitionHeader(T_dynamicalRepartition * tabRepartition, 867 int sizeOfTab, 868 char * P_repartitionName) 869 { 870 static char repartitionHeader[MAX_REPARTITION_HEADER_LENGTH]; 871 char buffer[MAX_CHAR_BUFFER_SIZE]; 872 873 if(tabRepartition != NULL) 874 { 875 sprintf(repartitionHeader, "%s%s", P_repartitionName, stat_delimiter); 876 for(int i=0; i<(sizeOfTab-1); i++) 877 { 878 sprintf(buffer, "<%d%s", tabRepartition[i].borderMax, stat_delimiter); 879 strcat(repartitionHeader, buffer); 880 } 881 sprintf(buffer, ">=%d%s", tabRepartition[sizeOfTab-1].borderMax, stat_delimiter); 882 strcat(repartitionHeader, buffer); 883 } 884 else 885 { 886 repartitionHeader[0] = '\0'; 887 } 888 889 return(repartitionHeader); 890 } 891 892 char* CStat::sRepartitionInfo(T_dynamicalRepartition * tabRepartition, 893 int sizeOfTab) 894 { 895 static char repartitionInfo[MAX_REPARTITION_INFO_LENGTH]; 896 char buffer[MAX_CHAR_BUFFER_SIZE]; 897 898 if(tabRepartition != NULL) 899 { 900 // if a repartition is present, this field match the repartition name 901 sprintf(repartitionInfo, stat_delimiter); 902 for(int i=0; i<(sizeOfTab-1); i++) 903 { 904 sprintf(buffer, "%lu%s", tabRepartition[i].nbInThisBorder, stat_delimiter); 905 strcat(repartitionInfo, buffer); 906 } 907 sprintf(buffer, "%lu%s", tabRepartition[sizeOfTab-1].nbInThisBorder, stat_delimiter); 908 strcat(repartitionInfo, buffer); 909 } 910 else 911 { 912 repartitionInfo[0] = '\0'; 913 } 914 915 return(repartitionInfo); 916 } 917 918 919 void CStat::displayRepartition(FILE *f, 920 T_dynamicalRepartition * tabRepartition, 921 int sizeOfTab) 922 { 923 if(tabRepartition != NULL) { 924 for(int i=0; i<(sizeOfTab-1); i++) { 925 if(i==0) { 926 DISPLAY_REPART(0, tabRepartition[i].borderMax, 927 tabRepartition[i].nbInThisBorder); 928 } else { 929 DISPLAY_REPART(tabRepartition[i-1].borderMax, 930 tabRepartition[i].borderMax, 931 tabRepartition[i].nbInThisBorder); 932 } 933 } 934 DISPLAY_LAST_REPART (tabRepartition[sizeOfTab-1].borderMax, 935 tabRepartition[sizeOfTab-1].nbInThisBorder); 936 } else { 937 DISPLAY_INFO (" <No repartion defined>"); 938 } 939 } 940 941 void CStat::displayData (FILE *f) 942 { 943 long localElapsedTime, globalElapsedTime ; 944 struct timeval currentTime; 945 float averageCallRate; 946 float realInstantCallRate; 947 unsigned long numberOfCall; 948 949 GET_TIME (¤tTime); 950 // computing the real call rate 951 globalElapsedTime = computeDiffTimeInMs (¤tTime, &M_startTime); 952 localElapsedTime = computeDiffTimeInMs (¤tTime, &M_pdStartTime); 953 954 // the call rate is for all the call : incoming and outgoing 955 numberOfCall = M_counters[CPT_C_IncomingCallCreated] + 956 M_counters[CPT_C_OutgoingCallCreated]; 957 averageCallRate = (globalElapsedTime > 0 ? 958 1000*(float)numberOfCall/(float)globalElapsedTime 959 : 0.0); 960 numberOfCall = (M_counters[CPT_PD_IncomingCallCreated] + 961 M_counters[CPT_PD_OutgoingCallCreated]); 962 realInstantCallRate = (localElapsedTime > 0 ? 963 1000*(float)numberOfCall / (float)localElapsedTime : 964 0.0); 965 966 // display info 967 DISPLAY_DLINE (); 968 // build and display header info 969 DISPLAY_TXT ("Start Time ", formatTime(&M_startTime)); 970 DISPLAY_TXT ("Last Reset Time", formatTime(&M_pdStartTime)); 971 DISPLAY_TXT ("Current Time", formatTime(¤tTime)); 972 973 // printing the header in the middle 974 DISPLAY_CROSS_LINE(); 975 DISPLAY_HEADER(); 976 DISPLAY_CROSS_LINE(); 977 978 DISPLAY_TXT_COL ("Elapsed Time", 979 msToHHMMSSmmm(localElapsedTime), 980 msToHHMMSSmmm(globalElapsedTime)); 981 982 DISPLAY_VAL_RATEF_COL ("Call Rate", 983 realInstantCallRate, 984 averageCallRate); 985 DISPLAY_CROSS_LINE (); 986 987 DISPLAY_2VAL ("Incoming call created", 988 M_counters[CPT_PD_IncomingCallCreated], 989 M_counters[CPT_C_IncomingCallCreated]); 990 DISPLAY_2VAL ("OutGoing call created", 991 M_counters[CPT_PD_OutgoingCallCreated], 992 M_counters[CPT_C_OutgoingCallCreated]); 993 DISPLAY_CUMUL ("Total Call created", M_counters[CPT_C_IncomingCallCreated] + 994 M_counters[CPT_C_OutgoingCallCreated]); 995 DISPLAY_PERIO ("Current Call", M_counters[CPT_C_CurrentCall]); 996 997 bool first = true; 998 for (int i = 0; i < MAX_COUNTER; i++) { 999 char s[20]; 1000 1001 if (M_counters[CPT_C_Generic + i] == 0) { 1002 continue; 1003 } 1004 1005 if (first) { 1006 DISPLAY_CROSS_LINE (); 1007 first = false; 1008 } 1009 1010 sprintf(s, "Generic counter %d", i + 1); 1011 1012 DISPLAY_2VAL(s, M_counters[CPT_PD_Generic + i], M_counters[CPT_C_Generic + i]); 1013 } 1014 1015 DISPLAY_CROSS_LINE (); 1016 DISPLAY_2VAL ("Successful call", 1017 M_counters[CPT_PD_SuccessfulCall], 1018 M_counters[CPT_C_SuccessfulCall]); 1019 DISPLAY_2VAL ("Failed call", 1020 M_counters[CPT_PD_FailedCall], 1021 M_counters[CPT_C_FailedCall]); 1022 // DISPLAY_2VAL ("Unexpected msg", 1023 // M_counters[CPT_PD_UnexpectedMessage], 1024 // M_counters[CPT_C_UnexpectedMessage]); 1025 1026 DISPLAY_CROSS_LINE (); 1027 for (int i = 0; i < MAX_RTD_INFO_LENGTH; i++) { 1028 char s[15]; 1029 1030 if (!rtd_stopped[i]) { 1031 continue; 1032 } 1033 1034 sprintf(s, "Response Time %d", i + 1); 1035 DISPLAY_TXT_COL (s, 1036 msToHHMMSSmmm( (unsigned long)computeMean((E_CounterName)(CPT_PD_AverageResponseTime_Sum + i), (E_CounterName)(CPT_PD_NbOfCallUsedForAverageResponseTime + i)) ), 1037 msToHHMMSSmmm( (unsigned long)computeMean((E_CounterName)(CPT_C_AverageResponseTime_Sum + i), (E_CounterName)(CPT_C_NbOfCallUsedForAverageResponseTime + i)) ) ); 1038 } 1039 DISPLAY_TXT_COL ("Call Length", 1040 msToHHMMSSmmm( (unsigned long)computeMean(CPT_PD_AverageCallLength_Sum, CPT_PD_NbOfCallUsedForAverageCallLength)), 1041 msToHHMMSSmmm( (unsigned long)computeMean(CPT_C_AverageCallLength_Sum, CPT_C_NbOfCallUsedForAverageCallLength) )); 1042 DISPLAY_CROSS_LINE (); 1043 1044 for (int i = 0; i < MAX_RTD_INFO_LENGTH; i++) { 1045 char s[50]; 1046 1047 if (!rtd_stopped[i]) { 1048 continue; 1049 } 1050 1051 sprintf(s, "Average Response Time Repartition, %d", i + 1); 1052 DISPLAY_INFO(s); 1053 displayRepartition(f, M_ResponseTimeRepartition[i], M_SizeOfResponseTimeRepartition); 1054 } 1055 DISPLAY_INFO("Average Call Length Repartition"); 1056 displayRepartition(f, M_CallLengthRepartition, M_SizeOfCallLengthRepartition); 1057 1058 // DISPLAY_VAL ("NbCall Average RT(P)", 1059 // M_counters[CPT_PD_NbOfCallUsedForAverageResponseTime]); 1060 // DISPLAY_VAL ("NbCall Average RT", 1061 // M_counters[CPT_C_NbOfCallUsedForAverageResponseTime]); 1062 // DISPLAY_VAL ("NbCall Average CL", 1063 // M_counters[CPT_C_NbOfCallUsedForAverageCallLength]); 1064 // DISPLAY_VAL ("NbCall Average CL(P)", 1065 // M_counters[CPT_PD_NbOfCallUsedForAverageCallLength]); 1066 DISPLAY_DLINE (); 1067 } /* end of displayData () */ 1068 1069 1070 void CStat::displayStat (FILE *f) 1071 { 1072 long localElapsedTime, globalElapsedTime ; 1073 struct timeval currentTime; 1074 float averageCallRate; 1075 float realInstantCallRate; 1076 unsigned long numberOfCall; 1077 1078 GET_TIME (¤tTime); 1079 // computing the real call rate 1080 globalElapsedTime = computeDiffTimeInMs (¤tTime, &M_startTime); 1081 localElapsedTime = computeDiffTimeInMs (¤tTime, &M_pdStartTime); 1082 // the call rate is for all the call : incoming and outgoing 1083 numberOfCall = (M_counters[CPT_C_IncomingCallCreated] + 1084 M_counters[CPT_C_OutgoingCallCreated]); 1085 averageCallRate = (globalElapsedTime > 0 ? 1086 1000*(float)numberOfCall/(float)globalElapsedTime : 1087 0.0); 1088 numberOfCall = (M_counters[CPT_PD_IncomingCallCreated] + 1089 M_counters[CPT_PD_OutgoingCallCreated]); 1090 realInstantCallRate = (localElapsedTime > 0 ? 1091 1000*(float)numberOfCall / (float)localElapsedTime : 1092 0.0); 1093 1094 // build and display header info 1095 DISPLAY_TXT ("Start Time ", formatTime(&M_startTime)); 1096 DISPLAY_TXT ("Last Reset Time", formatTime(&M_pdStartTime)); 1097 DISPLAY_TXT ("Current Time", formatTime(¤tTime)); 1098 1099 // printing the header in the middle 1100 DISPLAY_CROSS_LINE(); 1101 DISPLAY_HEADER(); 1102 DISPLAY_CROSS_LINE(); 1103 1104 DISPLAY_TXT_COL ("Elapsed Time", 1105 msToHHMMSSmmm(localElapsedTime), 1106 msToHHMMSSmmm(globalElapsedTime)); 1107 1108 DISPLAY_VAL_RATEF_COL ("Call Rate", realInstantCallRate, averageCallRate); 1109 DISPLAY_CROSS_LINE (); 1110 1111 DISPLAY_2VAL ("Incoming call created", 1112 M_counters[CPT_PD_IncomingCallCreated], 1113 M_counters[CPT_C_IncomingCallCreated]); 1114 DISPLAY_2VAL ("OutGoing call created", 1115 M_counters[CPT_PD_OutgoingCallCreated], 1116 M_counters[CPT_C_OutgoingCallCreated]); 1117 DISPLAY_CUMUL ("Total Call created", M_counters[CPT_C_IncomingCallCreated] + 1118 M_counters[CPT_C_OutgoingCallCreated]); 1119 DISPLAY_PERIO ("Current Call", 1120 M_counters[CPT_C_CurrentCall]); 1121 1122 bool first = true; 1123 for (int i = 0; i < MAX_COUNTER; i++) { 1124 char s[20]; 1125 1126 if (M_counters[CPT_C_Generic + i] == 0) { 1127 continue; 1128 } 1129 1130 if (first) { 1131 DISPLAY_CROSS_LINE (); 1132 first = false; 1133 } 1134 1135 sprintf(s, "Generic counter %d", i + 1); 1136 1137 DISPLAY_2VAL(s, M_counters[CPT_PD_Generic + i], M_counters[CPT_C_Generic + i]); 1138 } 1139 1140 DISPLAY_CROSS_LINE (); 1141 DISPLAY_2VAL ("Successful call", 1142 M_counters[CPT_PD_SuccessfulCall], 1143 M_counters[CPT_C_SuccessfulCall]); 1144 DISPLAY_2VAL ("Failed call", 1145 M_counters[CPT_PD_FailedCall], 1146 M_counters[CPT_C_FailedCall]); 1147 //DISPLAY_2VAL ("Unexpected msg", 1148 // M_counters[CPT_PD_UnexpectedMessage], 1149 // M_counters[CPT_C_UnexpectedMessage]); 1150 1151 DISPLAY_CROSS_LINE (); 1152 for (int i = 0; i < MAX_RTD_INFO_LENGTH; i++) { 1153 char s[20]; 1154 1155 if (!rtd_stopped[i]) { 1156 continue; 1157 } 1158 1159 1160 sprintf(s, "Response Time %d", i + 1); 1161 DISPLAY_TXT_COL (s, 1162 msToHHMMSSmmm( (unsigned long)computeMean((E_CounterName)(CPT_PD_AverageResponseTime_Sum + i), (E_CounterName)(CPT_PD_NbOfCallUsedForAverageResponseTime + i)) ), 1163 msToHHMMSSmmm( (unsigned long)computeMean((E_CounterName)(CPT_C_AverageResponseTime_Sum + i), (E_CounterName)(CPT_C_NbOfCallUsedForAverageResponseTime + i)))); 1164 } 1165 DISPLAY_TXT_COL ("Call Length", 1166 msToHHMMSSmmm( (unsigned long)computeMean(CPT_PD_AverageCallLength_Sum, CPT_PD_NbOfCallUsedForAverageCallLength ) ), 1167 msToHHMMSSmmm( (unsigned long)computeMean(CPT_C_AverageCallLength_Sum, CPT_C_NbOfCallUsedForAverageCallLength) )); 1168 } 1169 1170 void CStat::displayRepartition (FILE *f) 1171 { 1172 DISPLAY_INFO("Average Response Time Repartition"); 1173 displayRepartition(f, 1174 M_ResponseTimeRepartition[0], 1175 M_SizeOfResponseTimeRepartition); 1176 DISPLAY_INFO("Average Call Length Repartition"); 1177 displayRepartition(f, 1178 M_CallLengthRepartition, 1179 M_SizeOfCallLengthRepartition); 1180 } 1181 1182 void CStat::displaySecondaryRepartition (FILE *f, int which) 1183 { 1184 DISPLAY_INFO("Average Response Time Repartition"); 1185 displayRepartition(f, 1186 M_ResponseTimeRepartition[which], 1187 M_SizeOfResponseTimeRepartition); 1188 } 1189 1190 1191 void CStat::dumpData () 1192 { 1193 long localElapsedTime, globalElapsedTime ; 1194 struct timeval currentTime; 1195 float averageCallRate; 1196 float realInstantCallRate; 1197 unsigned long numberOfCall; 1198 1199 // computing the real call rate 1200 GET_TIME (¤tTime); 1201 globalElapsedTime = computeDiffTimeInMs (¤tTime, &M_startTime); 1202 localElapsedTime = computeDiffTimeInMs (¤tTime, &M_plStartTime); 1203 1204 // the call rate is for all the call : incoming and outgoing 1205 numberOfCall = (M_counters[CPT_C_IncomingCallCreated] + 1206 M_counters[CPT_C_OutgoingCallCreated]); 1207 averageCallRate = (globalElapsedTime > 0 ? 1208 1000*(float)numberOfCall/(float)globalElapsedTime : 1209 0.0); 1210 numberOfCall = (M_counters[CPT_PL_IncomingCallCreated] + 1211 M_counters[CPT_PL_OutgoingCallCreated]); 1212 realInstantCallRate = (localElapsedTime > 0 ? 1213 1000*(float)numberOfCall / (float)localElapsedTime : 1214 0.0); 1215 1216 if(M_outputStream == NULL) { 1217 // if the file is still not opened, we opened it now 1218 M_outputStream = new ofstream(M_fileName); 1219 M_headerAlreadyDisplayed = false; 1220 1221 if(M_outputStream == NULL) { 1222 cerr << "Unable to open stat file '" << M_fileName << "' !" << endl; 1223 exit(EXIT_FATAL_ERROR); 1224 } 1225 1226 #ifndef __osf__ 1227 if(!M_outputStream->is_open()) 1228 { 1229 cerr << "Unable to open stat file '" << M_fileName << "' !" << endl; 1230 exit(EXIT_FATAL_ERROR); 1231 } 1232 #endif 1233 1234 } 1235 1236 if(M_headerAlreadyDisplayed == false) { 1237 // header - it's dump in file only one time at the beginning of the file 1238 (*M_outputStream) << "StartTime" << stat_delimiter 1239 << "LastResetTime" << stat_delimiter 1240 << "CurrentTime" << stat_delimiter 1241 << "ElapsedTime(P)" << stat_delimiter 1242 << "ElapsedTime(C)" << stat_delimiter 1243 << "CallRate(P)" << stat_delimiter 1244 << "CallRate(C)" << stat_delimiter 1245 << "IncomingCall(P)" << stat_delimiter 1246 << "IncomingCall(C)" << stat_delimiter 1247 << "OutgoingCall(P)" << stat_delimiter 1248 << "OutgoingCall(C)" << stat_delimiter 1249 << "TotalCallCreated" << stat_delimiter 1250 << "CurrentCall" << stat_delimiter 1251 << "SuccessfulCall(P)" << stat_delimiter 1252 << "SuccessfulCall(C)" << stat_delimiter 1253 << "FailedCall(P)" << stat_delimiter 1254 << "FailedCall(C)" << stat_delimiter 1255 << "FailedCannotSendMessage(P)" << stat_delimiter 1256 << "FailedCannotSendMessage(C)" << stat_delimiter 1257 << "FailedMaxUDPRetrans(P)" << stat_delimiter 1258 << "FailedMaxUDPRetrans(C)" << stat_delimiter 1259 << "FailedUnexpectedMessage(P)" << stat_delimiter 1260 << "FailedUnexpectedMessage(C)" << stat_delimiter 1261 << "FailedCallRejected(P)" << stat_delimiter 1262 << "FailedCallRejected(C)" << stat_delimiter 1263 << "FailedCmdNotSent(P)" << stat_delimiter 1264 << "FailedCmdNotSent(C)" << stat_delimiter 1265 << "FailedRegexpDoesntMatch(P)" << stat_delimiter 1266 << "FailedRegexpDoesntMatch(C)" << stat_delimiter 1267 << "FailedRegexpHdrNotFound(P)" << stat_delimiter 1268 << "FailedRegexpHdrNotFound(C)" << stat_delimiter 1269 << "FailedOutboundCongestion(P)" << stat_delimiter 1270 << "FailedOutboundCongestion(C)" << stat_delimiter 1271 << "FailedTimeoutOnRecv(P)" << stat_delimiter 1272 << "FailedTimeoutOnRecv(C)" << stat_delimiter 1273 << "FailedTimeoutOnSend(P)" << stat_delimiter 1274 << "FailedTimeoutOnSend(C)" << stat_delimiter 1275 << "OutOfCallMsgs(P)" << stat_delimiter 1276 << "OutOfCallMsgs(C)" << stat_delimiter 1277 << "Retransmissions(P)" << stat_delimiter 1278 << "Retransmissions(C)" << stat_delimiter 1279 << "AutoAnswered(P)" << stat_delimiter 1280 << "AutoAnswered(C)" << stat_delimiter; 1281 1282 for (int i = 0; i < MAX_RTD_INFO_LENGTH; i++) { 1283 char s_P[30]; 1284 char s_C[30]; 1285 1286 if (!rtd_stopped[i]) { 1287 continue; 1288 } 1289 1290 sprintf(s_P, "ResponseTime%d(P)%s", i + 1, stat_delimiter); 1291 sprintf(s_C, "ResponseTime%d(C)%s", i + 1, stat_delimiter); 1292 1293 (*M_outputStream) << s_P << s_C; 1294 1295 sprintf(s_P, "ResponseTime%dStDev(P)%s", i + 1, stat_delimiter); 1296 sprintf(s_C, "ResponseTime%dStDev(C)%s", i + 1, stat_delimiter); 1297 1298 (*M_outputStream) << s_P << s_C; 1299 } 1300 1301 (*M_outputStream) << "CallLength(P)" << stat_delimiter 1302 << "CallLength(C)" << stat_delimiter; 1303 (*M_outputStream) << "CallLengthStDev(P)" << stat_delimiter 1304 << "CallLengthStDev(C)" << stat_delimiter; 1305 for (int i = 0; i < MAX_COUNTER; i++) { 1306 (*M_outputStream) << "GenericCounter" << (i + 1) << "(P)" << stat_delimiter; 1307 (*M_outputStream) << "GenericCounter" << (i + 1) << "(C)" << stat_delimiter; 1308 } 1309 for (int i = 0; i < MAX_RTD_INFO_LENGTH; i++) { 1310 char s[30]; 1311 1312 if (!rtd_stopped[i]) { 1313 continue; 1314 } 1315 1316 sprintf(s, "ResponseTimeRepartition%d", i + 1); 1317 (*M_outputStream) << sRepartitionHeader(M_ResponseTimeRepartition[i], 1318 M_SizeOfResponseTimeRepartition, 1319 s); 1320 } 1321 (*M_outputStream) << sRepartitionHeader(M_CallLengthRepartition, 1322 M_SizeOfCallLengthRepartition, 1323 (char*) "CallLengthRepartition"); 1324 (*M_outputStream) << endl; 1325 M_headerAlreadyDisplayed = true; 1326 } 1327 1328 // content 1329 (*M_outputStream) << formatTime(&M_startTime) << stat_delimiter; 1330 (*M_outputStream) << formatTime(&M_plStartTime) << stat_delimiter; 1331 (*M_outputStream) << formatTime(¤tTime) << stat_delimiter 1332 << msToHHMMSS(localElapsedTime) << stat_delimiter; 1333 (*M_outputStream) << msToHHMMSS(globalElapsedTime) << stat_delimiter 1334 << realInstantCallRate << stat_delimiter 1335 << averageCallRate << stat_delimiter 1336 << M_counters[CPT_PL_IncomingCallCreated] << stat_delimiter 1337 << M_counters[CPT_C_IncomingCallCreated] << stat_delimiter 1338 << M_counters[CPT_PL_OutgoingCallCreated] << stat_delimiter 1339 << M_counters[CPT_C_OutgoingCallCreated] << stat_delimiter 1340 << (M_counters[CPT_C_IncomingCallCreated]+ 1341 M_counters[CPT_C_OutgoingCallCreated])<< stat_delimiter 1342 << M_counters[CPT_C_CurrentCall] << stat_delimiter 1343 << M_counters[CPT_PL_SuccessfulCall] << stat_delimiter 1344 << M_counters[CPT_C_SuccessfulCall] << stat_delimiter 1345 << M_counters[CPT_PL_FailedCall] << stat_delimiter 1346 << M_counters[CPT_C_FailedCall] << stat_delimiter 1347 << M_counters[CPT_PL_FailedCallCannotSendMessage] << stat_delimiter 1348 << M_counters[CPT_C_FailedCallCannotSendMessage] << stat_delimiter 1349 << M_counters[CPT_PL_FailedCallMaxUdpRetrans] << stat_delimiter 1350 << M_counters[CPT_C_FailedCallMaxUdpRetrans ] << stat_delimiter 1351 << M_counters[CPT_PL_FailedCallUnexpectedMessage] << stat_delimiter 1352 << M_counters[CPT_C_FailedCallUnexpectedMessage] << stat_delimiter 1353 << M_counters[CPT_PL_FailedCallCallRejected] << stat_delimiter 1354 << M_counters[CPT_C_FailedCallCallRejected] << stat_delimiter 1355 << M_counters[CPT_PL_FailedCallCmdNotSent] << stat_delimiter 1356 << M_counters[CPT_C_FailedCallCmdNotSent] << stat_delimiter 1357 << M_counters[CPT_PL_FailedCallRegexpDoesntMatch] << stat_delimiter 1358 << M_counters[CPT_C_FailedCallRegexpDoesntMatch] << stat_delimiter 1359 << M_counters[CPT_PL_FailedCallRegexpHdrNotFound] << stat_delimiter 1360 << M_counters[CPT_C_FailedCallRegexpHdrNotFound] << stat_delimiter 1361 << M_counters[CPT_PL_FailedOutboundCongestion] << stat_delimiter 1362 << M_counters[CPT_C_FailedOutboundCongestion] << stat_delimiter 1363 << M_counters[CPT_PL_FailedTimeoutOnRecv] << stat_delimiter 1364 << M_counters[CPT_C_FailedTimeoutOnRecv] << stat_delimiter 1365 << M_counters[CPT_PL_FailedTimeoutOnSend] << stat_delimiter 1366 << M_counters[CPT_C_FailedTimeoutOnSend] << stat_delimiter 1367 << M_counters[CPT_PL_OutOfCallMsgs] << stat_delimiter 1368 << M_counters[CPT_C_OutOfCallMsgs] << stat_delimiter 1369 << M_counters[CPT_PL_Retransmissions] << stat_delimiter 1370 << M_counters[CPT_C_Retransmissions] << stat_delimiter 1371 << M_counters[CPT_PL_AutoAnswered] << stat_delimiter 1372 << M_counters[CPT_C_AutoAnswered] << stat_delimiter; 1373 1374 // SF917289 << M_counters[CPT_C_UnexpectedMessage] << stat_delimiter; 1375 for (int i = 0; i < MAX_RTD_INFO_LENGTH; i++) { 1376 if (!rtd_stopped[i]) { 1377 continue; 1378 } 1379 1380 (*M_outputStream) 1381 << msToHHMMSSmmm( (unsigned long)computeMean((E_CounterName)(CPT_PL_AverageResponseTime_Sum + i), 1382 (E_CounterName)(CPT_PL_NbOfCallUsedForAverageResponseTime + i))) << stat_delimiter; 1383 (*M_outputStream) 1384 << msToHHMMSSmmm( (unsigned long)computeMean((E_CounterName)(CPT_C_AverageResponseTime_Sum + i), 1385 (E_CounterName)(CPT_C_NbOfCallUsedForAverageResponseTime + i))) << stat_delimiter; 1386 1387 (*M_outputStream) 1388 << msToHHMMSSmmm( (unsigned long)computeStdev((E_CounterName)(CPT_PL_AverageResponseTime_Sum + i), 1389 (E_CounterName)(CPT_PL_NbOfCallUsedForAverageResponseTime + i), 1390 (E_CounterName)(CPT_PL_AverageResponseTime_Squares + i)) ) << stat_delimiter; 1391 (*M_outputStream) 1392 << msToHHMMSSmmm( (unsigned long)computeStdev((E_CounterName)(CPT_C_AverageResponseTime_Sum + i), 1393 (E_CounterName)(CPT_C_NbOfCallUsedForAverageResponseTime + i), 1394 (E_CounterName)(CPT_C_AverageResponseTime_Squares + i)) ) << stat_delimiter; 1395 } 1396 (*M_outputStream) 1397 << msToHHMMSSmmm( (unsigned long)computeMean(CPT_PL_AverageCallLength_Sum, CPT_PL_NbOfCallUsedForAverageCallLength) ) << stat_delimiter; 1398 (*M_outputStream) 1399 << msToHHMMSSmmm( (unsigned long)computeMean(CPT_C_AverageCallLength_Sum, CPT_C_NbOfCallUsedForAverageCallLength) ) << stat_delimiter; 1400 (*M_outputStream) 1401 << msToHHMMSSmmm( (unsigned long)computeStdev(CPT_PL_AverageCallLength_Sum, 1402 CPT_PL_NbOfCallUsedForAverageCallLength, 1403 CPT_PL_AverageCallLength_Squares )) << stat_delimiter; 1404 (*M_outputStream) 1405 << msToHHMMSSmmm( (unsigned long)computeStdev(CPT_C_AverageCallLength_Sum, 1406 CPT_C_NbOfCallUsedForAverageCallLength, 1407 CPT_C_AverageCallLength_Squares )) << stat_delimiter; 1408 1409 for (int i = 0; i < MAX_COUNTER; i++) { 1410 (*M_outputStream) << M_counters[CPT_PL_Generic + i] << stat_delimiter; 1411 (*M_outputStream) << M_counters[CPT_C_Generic + i] << stat_delimiter; 1412 } 1413 1414 for (int i = 0; i < MAX_RTD_INFO_LENGTH; i++) { 1415 if (!rtd_stopped[i]) { 1416 continue; 1417 } 1418 (*M_outputStream) 1419 << sRepartitionInfo(M_ResponseTimeRepartition[i], 1420 M_SizeOfResponseTimeRepartition); 1421 } 1422 (*M_outputStream) 1423 << sRepartitionInfo(M_CallLengthRepartition, 1424 M_SizeOfCallLengthRepartition); 1425 (*M_outputStream) << endl; 1426 1427 // flushing the output file to let the tail -f working ! 1428 (*M_outputStream).flush(); 1429 1430 } /* end of logData () */ 1431 1432 void CStat::dumpDataRtt () 1433 { 1434 if(M_outputStreamRtt == NULL) { 1435 // if the file is still not opened, we opened it now 1436 M_outputStreamRtt = new ofstream(M_fileNameRtt); 1437 M_headerAlreadyDisplayedRtt = false; 1438 1439 if(M_outputStreamRtt == NULL) { 1440 cerr << "Unable to open rtt file '" << M_fileNameRtt << "' !" << endl; 1441 exit(EXIT_FATAL_ERROR); 1442 } 1443 1444 #ifndef __osf__ 1445 if(!M_outputStreamRtt->is_open()) 1446 { 1447 cerr << "Unable to open rtt file '" << M_fileNameRtt << "' !" << endl; 1448 exit(EXIT_FATAL_ERROR); 1449 } 1450 #endif 1451 } 1452 1453 if(M_headerAlreadyDisplayedRtt == false) { 1454 (*M_outputStreamRtt) << "Date_ms" << stat_delimiter 1455 << "response_time_ms" << stat_delimiter 1456 << "rtd_no" << endl; 1457 M_headerAlreadyDisplayedRtt = true; 1458 } 1459 1460 for (unsigned int L_i = 0; L_i < M_counterDumpRespTime ; L_i ++) { 1461 (*M_outputStreamRtt) << M_dumpRespTime[L_i].date << stat_delimiter ; 1462 (*M_outputStreamRtt) << M_dumpRespTime[L_i].rtt << stat_delimiter ; 1463 (*M_outputStreamRtt) << M_dumpRespTime[L_i].rtd_no << endl; 1464 (*M_outputStreamRtt).flush(); 1465 M_dumpRespTime[L_i].date = 0.0; 1466 M_dumpRespTime[L_i].rtt = 0.0; 1467 M_dumpRespTime[L_i].rtd_no = 0; 1468 } 1469 1470 // flushing the output file 1471 (*M_outputStreamRtt).flush(); 1472 1473 M_counterDumpRespTime = 0; 1474 } 1475 1476 1477 /* Time Gestion */ 1478 char* CStat::msToHHMMSS (unsigned long P_ms) 1479 { 1480 static char L_time [TIME_LENGTH]; 1481 unsigned long hh, mm, ss; 1482 1483 P_ms = P_ms / 1000; 1484 hh = P_ms / 3600; 1485 mm = (P_ms - hh * 3600) / 60; 1486 ss = P_ms - (hh * 3600) - (mm * 60); 1487 sprintf (L_time, "%2.2lu:%2.2lu:%2.2lu", hh, mm, ss); 1488 return (L_time); 1489 } /* end of msToHHMMSS */ 1490 1491 char* CStat::msToHHMMSSmmm (unsigned long P_ms) 1492 { 1493 static char L_time [TIME_LENGTH]; 1494 unsigned long sec, hh, mm, ss, mmm; 1495 1496 sec = P_ms / 1000; 1497 hh = sec / 3600; 1498 mm = (sec - hh * 3600) / 60; 1499 ss = sec - (hh * 3600) - (mm * 60); 1500 mmm = P_ms - (hh * 3600000) - (mm * 60000) - (ss*1000); 1501 sprintf (L_time, "%2.2lu:%2.2lu:%2.2lu:%3.3lu", hh, mm, ss, mmm); 1502 return (L_time); 1503 } /* end of msToHHMMSS */ 1504 1505 char* CStat::formatTime (struct timeval* P_tv, bool microseconds) 1506 { 1507 static char L_time [TIME_LENGTH]; 1508 struct tm * L_currentDate; 1509 1510 // Get the current date and time 1511 L_currentDate = localtime ((const time_t *)&P_tv->tv_sec); 1512 1513 // Format the time 1514 if (L_currentDate == NULL) 1515 { 1516 memset (L_time, 0, TIME_LENGTH); 1517 } 1518 else 1519 { 1520 if (microseconds) { 1521 sprintf(L_time, "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d:%03.03f", 1522 L_currentDate->tm_year + 1900, 1523 L_currentDate->tm_mon + 1, 1524 L_currentDate->tm_mday, 1525 L_currentDate->tm_hour, 1526 L_currentDate->tm_min, 1527 L_currentDate->tm_sec, 1528 (double)P_tv->tv_usec/(double)1000.0); 1529 } else { 1530 sprintf(L_time, "%4.4d-%2.2d-%2.2d\t%2.2d:%2.2d:%2.2d:%3.3d\t%10.10d.%6.6d", 1531 L_currentDate->tm_year + 1900, 1532 L_currentDate->tm_mon + 1, 1533 L_currentDate->tm_mday, 1534 L_currentDate->tm_hour, 1535 L_currentDate->tm_min, 1536 L_currentDate->tm_sec, 1537 (int) (P_tv->tv_usec)/1000, 1538 (long) (P_tv->tv_sec), 1539 (long) (P_tv->tv_usec)); 1540 } 1541 } 1542 return (L_time); 1543 } /* end of formatTime */ 1544 1545 long CStat::computeDiffTimeInMs (struct timeval* tf, struct timeval* ti) 1546 { 1547 long v1, v2; 1548 1549 v1 = tf->tv_sec - ti->tv_sec; 1550 v2 = tf->tv_usec - ti->tv_usec; 1551 if (v2 < 0) v2 += 1000000, v1--; 1552 return (v1*1000 + v2/1000); 1553 } 1554 1555 1556 CStat* CStat::M_instance = NULL; 1557 1558 /* Implementation of a fixed distribution. */ 1559 CFixed::CFixed(double value) { 1560 this->value = value; 1561 } 1562 double CFixed::sample() { 1563 return value; 1564 } 1565 int CFixed::textDescr(char *s, int len) { 1566 return snprintf(s, len, "%lf", value); 1567 } 1568 int CFixed::timeDescr(char *s, int len) { 1569 return time_string(value, s, len); 1570 } 1571 double CFixed::cdfInv(double percentile) { 1572 return value; 1573 } 1574 1575 /* Implementation of the default pause time. */ 1576 CDefaultPause::CDefaultPause() { 1577 } 1578 double CDefaultPause::sample() { 1579 return (double)duration; 1580 } 1581 int CDefaultPause::textDescr(char *s, int len) { 1582 return snprintf(s, len, "%d", duration); 1583 } 1584 int CDefaultPause::timeDescr(char *s, int len) { 1585 return time_string(duration, s, len); 1586 } 1587 double CDefaultPause::cdfInv(double percentile) { 1588 return duration; 1589 } 1590 1591 /* Implementation of a uniform distribution. */ 1592 static bool uniform_init = false; 1593 CUniform::CUniform(double min, double max) { 1594 if (!uniform_init) { 1595 uniform_init = true; 1596 srand(time(NULL)); 1597 } 1598 this->min = min; 1599 this->max = max; 1600 } 1601 double CUniform::sample() { 1602 double rval = ((double)rand())/((double)RAND_MAX); 1603 return min + (rval * (max - min)); 1604 } 1605 int CUniform::textDescr(char *s, int len) { 1606 return snprintf(s, len, "%lf/%lf", min, max); 1607 } 1608 int CUniform::timeDescr(char *s, int len) { 1609 int used = time_string(min, s, len); 1610 used += snprintf(s + used, len - used, "/"); 1611 used += time_string(max, s + used, len - used); 1612 return used; 1613 } 1614 double CUniform::cdfInv(double percentile) { 1615 return min + (max * percentile); 1616 } 1617 1618 #ifdef HAVE_GSL 1619 gsl_rng *gsl_init() { 1620 static gsl_rng *rng = NULL; 1621 1622 if (rng) { 1623 return rng; 1624 } 1625 1626 gsl_rng_env_setup(); 1627 rng = gsl_rng_alloc(gsl_rng_default); 1628 if (!rng) { 1629 ERROR("Could not initialize GSL random number generator.\n"); 1630 } 1631 1632 return rng; 1633 } 1634 1635 /* Normal distribution. */ 1636 CNormal::CNormal(double mean, double stdev) { 1637 this->mean = mean; 1638 this->stdev = stdev; 1639 rng = gsl_init(); 1640 } 1641 1642 double CNormal::sample() { 1643 double val = gsl_ran_gaussian(rng, stdev); 1644 return val + mean; 1645 } 1646 1647 int CNormal::textDescr(char *s, int len) { 1648 return snprintf(s, len, "N(%.3lf,%.3lf)", mean, stdev); 1649 } 1650 int CNormal::timeDescr(char *s, int len) { 1651 int used = 0; 1652 1653 used += snprintf(s, len, "N("); 1654 used += time_string(mean, s + used, len - used); 1655 used += snprintf(s + used, len - used, ","); 1656 used += time_string(stdev, s + used, len - used); 1657 used += snprintf(s + used, len - used, ")"); 1658 1659 return used; 1660 } 1661 double CNormal::cdfInv(double percentile) { 1662 return mean + gsl_cdf_gaussian_Pinv(percentile, stdev); 1663 } 1664 1665 /* Lognormal distribution. */ 1666 double CLogNormal::sample() { 1667 return gsl_ran_lognormal(rng, mean, stdev); 1668 } 1669 int CLogNormal::textDescr(char *s, int len) { 1670 if (len == 0) 1671 return 0; 1672 s[0] = 'L'; 1673 return 1 + this->CNormal::textDescr(s + 1, len - 1); 1674 } 1675 int CLogNormal::timeDescr(char *s, int len) { 1676 if (len == 0) 1677 return 0; 1678 s[0] = 'L'; 1679 return 1 + this->CNormal::timeDescr(s + 1, len - 1); 1680 } 1681 double CLogNormal::cdfInv(double percentile) { 1682 return gsl_cdf_lognormal_Pinv(percentile, mean, stdev); 1683 } 1684 1685 /* Exponential distribution. */ 1686 CExponential::CExponential(double mean) { 1687 this->mean = mean; 1688 rng = gsl_init(); 1689 } 1690 1691 double CExponential::sample() { 1692 return gsl_ran_exponential(rng, mean); 1693 } 1694 1695 int CExponential::textDescr(char *s, int len) { 1696 return snprintf(s, len, "Exp(%lf)", mean); 1697 } 1698 int CExponential::timeDescr(char *s, int len) { 1699 int used = snprintf(s, len, "Exp("); 1700 used += time_string(mean, s + used, len - used); 1701 used += snprintf(s + used, len - used, ")"); 1702 return used; 1703 } 1704 double CExponential::cdfInv(double percentile) { 1705 return gsl_cdf_exponential_Pinv(percentile, mean); 1706 } 1707 1708 /* Weibull distribution. */ 1709 CWeibull::CWeibull(double lambda, double k) { 1710 this->lambda = lambda; 1711 this->k = k; 1712 rng = gsl_init(); 1713 } 1714 1715 double CWeibull::sample() { 1716 return gsl_ran_weibull(rng, lambda, k); 1717 } 1718 1719 int CWeibull::textDescr(char *s, int len) { 1720 return snprintf(s, len, "Wb(%.3lf,%.3lf)", lambda, k); 1721 } 1722 int CWeibull::timeDescr(char *s, int len) { 1723 int used = 0; 1724 1725 used += snprintf(s, len, "Wb("); 1726 used += time_string(lambda, s + used, len - used); 1727 used += snprintf(s + used, len - used, ","); 1728 used += time_string(k, s + used, len - used); 1729 used += snprintf(s + used, len - used, ")"); 1730 1731 return used; 1732 } 1733 double CWeibull::cdfInv(double percentile) { 1734 return gsl_cdf_weibull_Pinv(percentile, lambda, k); 1735 } 1736 1737 /* Pareto distribution. */ 1738 CPareto::CPareto(double k, double xsubm) { 1739 this->k = k; 1740 this->xsubm = xsubm; 1741 rng = gsl_init(); 1742 } 1743 1744 double CPareto::sample() { 1745 return gsl_ran_pareto(rng, k, xsubm); 1746 } 1747 1748 int CPareto::textDescr(char *s, int len) { 1749 return snprintf(s, len, "P(%.3lf,%.3lf)", k, xsubm); 1750 } 1751 int CPareto::timeDescr(char *s, int len) { 1752 int used = 0; 1753 1754 used += snprintf(s, len, "P("); 1755 used += time_string(k, s + used, len - used); 1756 used += snprintf(s + used, len - used, ","); 1757 used += time_string(xsubm, s + used, len - used); 1758 used += snprintf(s + used, len - used, ")"); 1759 1760 return used; 1761 } 1762 double CPareto::cdfInv(double percentile) { 1763 return gsl_cdf_pareto_Pinv(percentile, k, xsubm); 1764 } 1765 1766 /* Gamma distribution. */ 1767 CGamma::CGamma(double k, double theta) { 1768 this->k = k; 1769 this->theta = theta; 1770 rng = gsl_init(); 1771 } 1772 1773 double CGamma::sample() { 1774 return gsl_ran_gamma(rng, k, theta); 1775 } 1776 1777 int CGamma::textDescr(char *s, int len) { 1778 return snprintf(s, len, "G(%.3lf,%.3lf)", k, theta); 1779 } 1780 int CGamma::timeDescr(char *s, int len) { 1781 int used = 0; 1782 1783 used += snprintf(s, len, "G("); 1784 used += time_string(k, s + used, len - used); 1785 used += snprintf(s + used, len - used, ","); 1786 used += time_string(theta, s + used, len - used); 1787 used += snprintf(s + used, len - used, ")"); 1788 1789 return used; 1790 } 1791 double CGamma::cdfInv(double percentile) { 1792 return gsl_cdf_gamma_Pinv(percentile, k, theta); 1793 } 1794 1795 /* NegBin distribution. */ 1796 CNegBin::CNegBin(double p, double n) { 1797 this->p = p; 1798 this->n = n; 1799 rng = gsl_init(); 1800 } 1801 1802 double CNegBin::sample() { 1803 return gsl_ran_negative_binomial(rng, n, p); 1804 } 1805 1806 int CNegBin::textDescr(char *s, int len) { 1807 return snprintf(s, len, "NB(%.3lf,%.3lf)", p, n); 1808 } 1809 int CNegBin::timeDescr(char *s, int len) { 1810 int used = 0; 1811 1812 used += snprintf(s, len, "NB("); 1813 used += time_string(p, s + used, len - used); 1814 used += snprintf(s + used, len - used, ","); 1815 used += time_string(n, s + used, len - used); 1816 used += snprintf(s + used, len - used, ")"); 1817 1818 return used; 1819 } 1820 /* We really don't implement this, but should so that sanity checking will 1821 * work. For now, just return zero. */ 1822 double CNegBin::cdfInv(double percentile) { 1823 return 0; 1824 } 1825 #endif 1826 1827
| No admin address has been configured | ViewVC Help |
| Powered by ViewVC 1.0.8 |