34 #ifndef _LOADRUNNER_UTILS_C 35 #define _LOADRUNNER_UTILS_C 42 #define _vUserID 0_vUserID_no_longer_exists_please_use_y_virtual_user_id_or_function_y_is_vugen_run 43 #define _vUserGroup 0_vUserGroup_no_longer_exists_please_use_y_virtual_user_group 59 unsigned long hash = 0;
66 hash = c + (hash << 6) + (hash << 16) - hash;
103 if( (0>lowerbound) || (lowerbound>upperbound) || (upperbound > rand_max) || (rand_max <= 0))
105 lr_error_message(
"y_rand_in_sliding_window called with nonsensical arguments: ( 0 <= %d < %d <= %d ) == FALSE",
106 lowerbound, upperbound, rand_max);
111 if( (roll >= lowerbound) && (roll <= upperbound) )
139 if (lowerbound > upperbound)
141 lr_error_message(
"y_rand_between(): lowerbound should be less than upperbound!");
144 return lowerbound +
y_drand() * (upperbound - lowerbound + 1);
165 char *tmp = lr_get_attrib_string(attrib);
170 lr_save_string(tmp, param);
227 case LR_REND_ALL_ARRIVED:
228 message =
"LR_REND_ALL_ARRIVED - Vuser was released after all the designated Vusers arrived.";
230 case LR_REND_TIMEOUT:
231 message =
"LR_REND_TIMEOUT - Vuser was released after the timeout value was reached.";
233 case LR_REND_DISABLED:
234 message =
"LR_REND_DISABLED - The rendezvous was disabled from the Controller.";
236 case LR_REND_NOT_FOUND:
237 message =
"LR_REND_NOT_FOUND - The rendezvous was not found.";
239 case LR_REND_VUSER_NOT_MEMBER:
240 message =
"LR_REND_VUSER_NOT_MEMBER - Vuser was not defined in the rendezvous.";
242 case LR_REND_VUSER_DISABLED:
243 message =
"LR_REND_VUSER_DISABLED - Vuser was disabled for the rendezvous.";
245 case LR_REND_BY_USER:
246 message =
"LR_REND_BY_USER - The rendezvous was released by the user.";
249 message =
"Unknown rendezvous result code.";
253 lr_log_message(
"Rendezvous returned: %s", message);
285 lr_message(
"---------------------------------------------------------------------------------");
289 lr_save_string(breadcrumb,
"breadcrumb");
293 lr_param_sprintf(
"breadcrumb",
"%s;%s", lr_eval_string(
"{breadcrumb}"), breadcrumb);
307 #define y_breadcrumb_reset() lr_save_string("", "breadcrumb") 335 lr_log_message(
"y_write_to_file(%s, %s)", filename, content);
337 if ((file =
fopen(filename,
"at")) == NULL)
339 lr_error_message (
"Cannot write to file >>%s<<", filename);
342 if (result =
fprintf(file,
"%s\n", content) <0)
378 unsigned long nLength;
382 lr_log_message(
"y_write_parameter_to_file(\"%s\", \"%s\")", filename, content_parameter);
386 lr_eval_string_ext(param,
strlen(param), &szBuf, &nLength, 0, 0, -1);
390 if( !(fp =
fopen(filename,
"wb")) )
392 lr_error_message(
"Cannot open file %s for writing!", filename);
393 lr_eval_string_ext_free(&szBuf);
399 if( (result =
fwrite(szBuf, 1, nLength, fp)) < nLength )
401 lr_error_message(
"Error while writing %d bytes to file: %s ; Only %d bytes were written.", nLength, filename, result);
411 if( (tmp =
fclose(fp)) != 0 )
413 lr_error_message(
"Error code %d while closing file %s", tmp, filename);
419 lr_eval_string_ext_free(&szBuf);
444 lr_save_datetime(
"%Y%m%d,%H%M%S", DATE_NOW,
"DATE_TIME_STRING");
468 int weekday, weeksOffset, weekstart;
470 int result = workdays;
480 lr_save_datetime(
"%w", DATE_NOW,
"weekdayToday");
481 weekstart =
atoi(lr_eval_string(
"{weekdayToday}"));
484 weeksOffset = result / 5;
486 result += (2 * weeksOffset);
490 lr_save_datetime(
"%w", DATE_NOW + result*(ONE_DAY),
"weekdayFuture");
491 weekday =
atoi(lr_eval_string(
"{weekdayFuture}"));
504 if( i == 0 || i == 6 ) {
509 }
while( i != (weekday+1) );
514 if ( weekday == 6 ) {
550 } FreeBytesAvailable = {0,0}, TotalNumberOfBytes = {0,0};
553 static int kernel_dll_loaded = 0;
554 if (!kernel_dll_loaded) {
555 const int le = 0x01020304;
557 if (
sizeof(
int) != 4 || *(
short*)&le != 0x304) {
558 lr_error_message(
"This system is not supported, expected 32bit little endian (%d %x)",
sizeof(
int), *(
short*)&le);
561 ret = lr_load_dll(
"kernel32.dll");
563 lr_log_error(
"Unable to load kernel32.dll. Error number %d. Unable to report disk space usage.", ret);
566 kernel_dll_loaded = 1;
571 if (GetDiskFreeSpaceExA(folder_name,
572 available ? &FreeBytesAvailable: NULL,
573 total ? &TotalNumberOfBytes : NULL,
575 && ((ret = GetLastError())|1)) {
577 FormatMessageA(0x1300, NULL, ret, 0, &lpMsgBuf, 0, NULL);
578 lr_error_message(
"GetDiskFreeSpaceEx returned Windows Error: (%d) %s", ret, lpMsgBuf);
586 *available = 4294967296. * FreeBytesAvailable.high + FreeBytesAvailable.low;
591 *total = 4294967296. * TotalNumberOfBytes.high + TotalNumberOfBytes.low;
606 double free_mebibytes;
608 free_mebibytes /= 1048576.;
609 lr_log_message(
"Free disk space for folder \"%s\": %.0lf MiB)", folder_name, free_mebibytes);
610 return free_mebibytes;
625 double available, total;
627 available = total ? available / total * 100. : 0.;
628 lr_log_message(
"Free disk space percentage for folder \"%s\": %.2lf%%", folder_name, available);
675 lr_log_message(
"y_read_file_into_parameter(%s, %s)", filename, param);
678 if( (f =
fopen(filename,
"rb")) == NULL )
680 lr_error_message(
"Unable to open file %s", filename);
690 fread(bytes, pos, 1, f);
696 lr_param_sprintf(
"y_byte_size_param_name",
"y_size_%s", param);
697 lr_save_int(pos, lr_eval_string(
"{y_byte_size_param_name}"));
699 lr_save_var(bytes, pos, 0, param);
730 return timebuffer.
time + (timebuffer.
millitm / 1000.);
743 if( current_time < timestamp )
745 double result = timestamp - current_time;
746 lr_force_think_time(result);
768 #define y_delay_once( delay_in_seconds ) \ 770 static int delay_done = 0; \ 775 lr_force_think_time(delay_in_seconds); \ 822 static double test_start_time = 0;
823 static double previous_time = 0;
825 double response_time;
830 if( test_start_time < 1 )
832 test_start_time = current_time;
833 previous_time = current_time;
837 time_passed = current_time - test_start_time;
838 response_time = current_time - previous_time;
841 lr_log_message(
"TT calculation: starttime %f, current time %f, previous time %f, virtual_users %d, rampup_period %d",
842 test_start_time, current_time, previous_time, virtual_users, rampup_period);
845 double TT, TPS_target;
846 double factor = time_passed / rampup_period;
850 else if( factor < 0.03 )
854 TPS_target = ((TPS_max - TPS_initial) * factor) + TPS_initial;
855 TT = (virtual_users / TPS_target) - response_time;
858 lr_log_message(
"TT: %f, time_passed: %f, factor %f, response_time %f, TPS_init %f, TPS_max %f, TPS_target %f",
859 TT, time_passed, factor, response_time, TPS_initial, TPS_max, TPS_target);
861 lr_user_data_point(
"y_thinktime", TT);
881 previous_time = current_time + TT;
901 const double TPS_initial = 0.1;
902 const int virtual_users = 1;
918 const int buffer_size = 10240;
924 char *command_evaluated = lr_eval_string(command);
926 lr_save_string(
"-- command not yet executed --",
"command_result");
927 lr_log_message(
"Executing command: %s", command_evaluated);
929 fp =
popen(command_evaluated,
"r");
931 lr_error_message(
"Error opening stream.");
936 count =
fread(buffer,
sizeof(
char), buffer_size, fp);
939 lr_error_message(
"Did not reach the end of the input stream when reading. Try increasing buffer_size.");
945 lr_error_message (
"I/O error during read.");
949 count =
fread(buffer,
sizeof(
char), (
sizeof buffer) - 1, fp);
950 lr_save_var(buffer, count, 0,
"command_output");
953 token = (
char*)
strtok(buffer,
"\n");
956 lr_save_string(
"",
"command_result");
960 lr_save_string(token,
"command_result");
967 while (token != NULL) {
968 sprintf(param_buf,
"output_%d", i);
969 lr_save_string(token, param_buf);
971 token = (
char*)
strtok(NULL,
"\n");
973 lr_save_int(i-1,
"output_count");
976 for (i=1; i<=lr_paramarr_len(
"output"); i++) {
977 lr_output_message(
"Parameter value: %s", lr_paramarr_idx(
"output", i));
1030 static int enabled = -1;
1031 static int pause_time = 900;
1032 static unsigned pacing_limit = 10, abort_limit = -1;
1033 static unsigned errorcount = 0;
1037 long tmp, tmp2, nr;
char *str;
1038 str = lr_get_attrib_string(
"errorcheck_enabled");
1045 str = lr_get_attrib_string(
"errorcheck_pause_time");
1046 if (!str) str = lr_get_attrib_string(
"errorcheck_pause_time_seconds");
1047 if (str && (nr =
sscanf(str,
"%d:%d", &tmp, &tmp2)) > 0) {
1049 pause_time = nr == 1 ? tmp: tmp * 60 + tmp2;
1052 str = lr_get_attrib_string(
"errorcheck_limit");
1053 if (str && (nr =
sscanf(str,
"%u/%u", &tmp, &tmp2)) > 0) {
1055 if (nr == 2) abort_limit = tmp2;
1058 lr_log_message(
"y_errorcheck() settings: -errorcheck_enabled%s -errorcheck_limit %d/%d -errorcheck_pause_time %u:%02d",
1059 enabled ?
"":
" 0", pacing_limit, abort_limit, pause_time / 60, pause_time % 60);
1062 if (!enabled)
return 0;
1064 if (ok) errorcount = 0;
1067 if (errorcount >= abort_limit)
1069 lr_error_message(
"y_errorcheck(): Too many errors occurred. Aborting.");
1070 lr_set_transaction(
"---TOO MANY ERRORS - ABORTING---", 0, LR_FAIL);
1074 if (errorcount >= pacing_limit)
1076 lr_error_message(
"y_errorcheck(): Too many errors occurred. Pausing %d seconds.", pause_time);
1077 lr_set_transaction(
"---TOO MANY ERRORS - THROTTLING LOAD---", 0, LR_FAIL);
1079 lr_force_think_time(pause_time);
1081 if (errorcount) lr_log_message(
"Number of failed iterations: %d", errorcount);
1082 lr_user_data_point(
"y_errorcheck_errorcount", errorcount);
1151 static double test_start_time = 0;
1152 static double total_pacing_time = 0;
1157 if( test_start_time < 1 )
1159 test_start_time = current_time;
1163 lr_log_message(
"Pacing calculation: starttime %f, current time %f, total pacing %d", test_start_time, current_time, total_pacing_time );
1166 double time_passed = current_time - test_start_time;
1167 double pacing_delta = total_pacing_time - time_passed;
1169 lr_user_data_point(
"y_pace", pacing_delta);
1170 if( pacing_delta > 0 )
1171 lr_force_think_time(pacing_delta);
1174 total_pacing_time += pacing_time_in_seconds;
1176 return pacing_delta;
1189 double y_pace_rnd(
double min_pacing_time_in_seconds,
double max_pacing_time_in_seconds)
1191 return y_pace(min_pacing_time_in_seconds +
y_drand() * (max_pacing_time_in_seconds - min_pacing_time_in_seconds);
1196 #endif // _LOADRUNNER_UTILS_C void ftime(struct _timeb *time)
Documented at http://www.qnx.com/developers/docs/6.5.0/topic/com.qnx.doc.neutrino_lib_ref/f/ftime.html .
int y_workdays_from_today(int workdays)
Calculate the difference in days between today and X workdays into the future.
double y_get_free_disk_space_in_mebibytes(const char *folder_name)
Get the amount of free disk space in the target folder in mebibytes (SI unit)
int y_read_file_into_parameter(char *filename, char *param)
Read the contents of a file into a single parameter.
double y_drand(void)
Generate a random number between 0 <= y_drand() < 1. This supersedes y_rand(). Equal to Math...
int y_errorcheck(int ok)
Errorflood guard. Also known as "the error check".
void y_get_disk_space(const char *folder_name, double *available, double *total)
Get the free disk space on the target folder on the load generator.
size_t fread(void *buffer, size_t size, size_t count, long file_pointer)
Documented at http://www.cplusplus.com/reference/cstdio/fread/.
int y_write_to_file(char *filename, char *content)
Write a string to a file.
int feof(long file_pointer)
Documented at http://www.cplusplus.com/reference/cstdio/feof/.
char * strtok(char *string, const char *delimiters)
Documented at http://www.cplusplus.com/reference/cstring/strtok/.
int fclose(long file_pointer)
Documented at http://www.cplusplus.com/reference/cstdio/fclose/.
char * y_mem_alloc(size_t size)
Ylib wrapper for malloc()
long fopen(const char *filename, const char *access_mode)
Documented at http://www.cplusplus.com/reference/cstdio/fopen/.
Contains core ylib support functions needed for the functioning of the library.
long ftell(long file_pointer)
Documented at http://www.cplusplus.com/reference/cstdio/ftell/.
int atoi(const char *string)
Documented at http://www.cplusplus.com/reference/cstdlib/atoi/.
void y_log_rendezvous_result(int result)
Process the result code of lr_rendezvous() call to log human readable errors.
double y_delay_until(double timestamp)
Delay until a certain time.
#define SEEK_SET
set file offset to offset
size_t fwrite(const void *buffer, size_t size, size_t count, long file_pointer)
Documented at http://www.cplusplus.com/reference/cstdio/fwrite/.
double y_pace(double pacing_time_in_seconds)
Improved implementation of loadrunner pacing.
char * y_get_parameter_eval_string(const char *param_name)
Obtain the string required to fetch the contents of a parameter through lr_eval_string().
long popen(const char *command, const char *access_mode)
Documented at http://man7.org/linux/man-pages/man3/popen.3.html .
double y_pace_rnd(double min_pacing_time_in_seconds, double max_pacing_time_in_seconds)
Improved implementation of loadrunner pacing - with semirandomized pacing.
void y_datetime()
Saves the current date/time into a LR-parameter.
int fprintf(long file_pointer, const char *format_string,...)
Documented at http://www.cplusplus.com/reference/cstdio/fprintf/.
int sprintf(char *buffer, const char *format_string,...)
Documented at http://www.cplusplus.com/reference/cstdio/sprintf/. You should prefer snprintf over s...
int sscanf(const char *buffer, const char *format_string,...)
Documented at http://www.cplusplus.com/reference/cstdio/sscanf/.
y_execute_shell_command(char *command, int debug)
Execute a windows shell command Implements proper error checking.
size_t strlen(const char *string)
Documented at http://www.cplusplus.com/reference/cstring/strlen/.
int y_is_empty_parameter(const char *param_name)
Test if the given parameter is empty or not yet set. (These are two different things..) It would be nice if loadrunner had a builtin for this.
void y_user_data_point(char *param)
Create a user data point for a parameter.
double y_think_time_for_rampup_ext(int rampup_period, double TPS_initial, double TPS_max, int virtual_users)
Ramp up the load by using varying amounts of think time instead of virtual users. ...
int y_write_parameter_to_file(char *filename, char *content_parameter)
Write the content of a parameter to a file.
static unsigned long y_hash_sdbm(char *str)
Create a hash of string input.
unsigned short millitm
Milliseconds. Actual accuracy may be lower.
int ferror(long file_pointer)
Documented at http://www.cplusplus.com/reference/cstdio/ferror/.
int fseek(long file_pointer, long offset, int origin)
Documented at http://www.cplusplus.com/reference/cstdio/fseek/.
#define SEEK_END
set file offset to EOF plus offset
int y_rand_in_sliding_window(int lowerbound, int upperbound, int rand_max)
Generate random number and test if it lies between 2 given boundaries.
char * y_get_parameter(const char *param_name)
Get the content of a parameter and return it as a char *.
void y_breadcrumb(char *breadcrumb)
Keep track of the steps in the script.
double y_think_time_for_rampup(const int rampup_period, double TPS_max)
Ramp up the load by using varying amounts of think time instead of virtual users. For simulating situ...
int y_save_attribute(char *param)
Fetch attribute from vUser's command lin and store it in a parameter of the same name. This will fetch an attribute from the vUser's command line (as set in the scenario or in runtime settings (addition attributes)) and stores it in a parameter of the same name. This function is a shortcut to y_save_attribute_to_parameter()
int y_rand_between(int lowerbound, int upperbound)
Create a random number between two boundaries. (the boundaries are included!)
double y_get_current_time()
Get the current time in seconds since 1970, as a double.
double y_get_free_disk_space_percentage(const char *folder_name)
Get the free disk space percentage on the target folder on the load generator.
void free(void *mem_address)
Documented at http://www.cplusplus.com/reference/cstdlib/free/.
time_t time
Time, in seconds, since the Unix Epoch, 1 January 1970 00:00:00 Coordinated Universal Time (UTC)...
int y_save_attribute_to_parameter(char *attrib, char *param)
Fetch attribute from vUser's command line and store it in a parameter. This will fetch an attribute f...
double atof(const char *string)
Documented at http://www.cplusplus.com/reference/cstdlib/atof/.
Used by ftime. Defined as _timeb (instead of timeb) just as in the on-line Help.
int pclose(long file_pointer)
Documented at http://man7.org/linux/man-pages/man3/pclose.3.html .