How to get unique file name in LoadRunner?

How to get unique file name in LoadRunner?

In my previous LoadRunner VIDEO post, I shown and explained how to record PDF file saving in LoadRunner.
The provided code works correctly in LoadRunner VuGen or in LoadRunner Controller for one concurrent user. Here it is:
//Truncate to zero length or create file for writing.
fp = fopen("c:\\temp\\_file.pdf","wb");

//Process the data ...

//Write the data to an output file.
fwrite(bufData, nSize, 1, fp);
If you try to run this code with several concurrent users, all of them will try to create the same file and write to it. As a result, this will led to the error.

How to resolve this problem?
Each user has to get unique file name and create a file with the unique name .


Now, I'm going to show - how to generate unique file name in LoadRunner.

The first step is to get a timestamp as a part of file name.
The timestamp consists of:
  • date (month, day, year)
  • time (hours, minutes, seconds, milliseconds)
You can use the following simple code to get a full timestamp without milliseconds:
lr_save_datetime("%m%d%Y_%H%M%S", DATE_NOW, "prmTimeStamp");
lr_output_message(lr_eval_string("Timestamp is: {prmTimeStamp}"));
The result of this code is:
(click the image to enlarge it)
Do you know what does the string "%m%d%Y_%H%M%S" mean?
These are Datetime Format Codes. Please, refer to a table for their descriptions:
#
Datetime Format Code
Description
1
%m
month number (01-12)
2
%d
day of month (01-31)
3
%Y
year, including century (for example, 1988)
4
%H
hour (00-23)
5
%M
minute (00-59)
6
%S
seconds (00-59)

The above code is not ideal. If you application (and LoadRunner script) saves more than one file per second, then file names will be dublicated.

That's why I can propose the code, which get a timestamp with milliseconds:
ent timestamp:
typedef long time_t;

struct _timeb {
    time_t time;
    unsigned short millitm;
    short timezone;
    short dstflag;
};

struct tm {
    int tm_sec; // seconds after the minute - [0,59]
    int tm_min; // minutes after the hour - [0,59]
    int tm_hour; // hours since midnight - [0,23]
    int tm_mday; // day of the month - [1,31]
    int tm_mon; // months since January - [0,11]
    int tm_year; // years since 1900
    int tm_wday; // days since Sunday - [0,6]
    int tm_yday; // days since January 1 - [0,365]
    int tm_isdst; // daylight savings time flag
    #ifdef LINUX
    int tm_gmtoff;
    const char * tm_zone;
    #endif
};

struct _timeb tb;
struct tm * now;
char szFileName[256];

_tzset(); // Sets variables used by localtime
_ftime(&tb); // Gets the current timestamp

// Convert to time structure
now = (struct tm *)localtime(&tb.time);

sprintf(szFileName, "%02d%02d%04d_%02d%02d%02d_%03u",
    now->tm_mon + 1,
    now->tm_mday,
    now->tm_year + 1900,
    now->tm_hour,
    now->tm_min,
    now->tm_sec,
    tb.millitm);
lr_output_message("Timestamp is: %s", szFileName);
Let's execute this code and check the result:
(click the image to enlarge it)
That's much better :) We can generate timestamp with millisecond.
Unfortunately, the chances that concurrent users will generate the same file name at the same time still exist.

To resolve this issue, we can get unique ids per virtual users. This can be done with lr_whoami LoadRunner function:
int vuserid, scid;
char *groupid;

lr_whoami(&vuserid, &groupid, &scid);
lr_message("Group: %s, vuser id: %d, scenario id %d", groupid, vuserid, scid);
lr_whoami LoadRunner function returns information about the Vuser executing the script.

When you run this code in LoadRunner Vuser Generator, the result will be:

When you run this code in LoadRunner Controller, the result will be:

So, the last step is to combine timestamp with a vuser execution's ids and use them as a file name.
This will guarantee, that each LoadRunner virtual user will have unique file name.

So, the final code is:
typedef long time_t;

struct _timeb {
    time_t time;
    unsigned short millitm;
    short timezone;
    short dstflag;
};

struct tm {
    int tm_sec; // seconds after the minute - [0,59]
    int tm_min; // minutes after the hour - [0,59]
    int tm_hour; // hours since midnight - [0,23]
    int tm_mday; // day of the month - [1,31]
    int tm_mon; // months since January - [0,11]
    int tm_year; // years since 1900
    int tm_wday; // days since Sunday - [0,6]
    int tm_yday; // days since January 1 - [0,365]
    int tm_isdst; // daylight savings time flag
    #ifdef LINUX
    int tm_gmtoff;
    const char * tm_zone;
    #endif
};

struct _timeb tb;
struct tm * now;
char szFileName[256];

int vuserid, scid;
char *vusergroup;

_tzset(); // Sets variables used by localtime
_ftime(&tb); // Gets the current timestamp

// Convert to time structure
now = (struct tm *)localtime(&tb.time);

sprintf(szFileName, "%02d%02d%04d_%02d%02d%02d_%03u_%d_%d_%s",
    now->tm_mon + 1,
    now->tm_mday,
    now->tm_year + 1900,
    now->tm_hour,
    now->tm_min,
    now->tm_sec,
    tb.millitm,
    vuserid,
    scid,
    vusergroup);

lr_output_message
("File name is: %s", szFileName);
Note: You can download this source code from here.

The result of above code is:
Using the generated name (05312008_221557_116_7_0_group1) you can save the file into "05312008_221557_116_7_0_group1.pdf" or "05312008_221557_116_7_0_group1.txt" depending on the file type.


Related articles:


I hope, this solution will help you in LoadRunner scripting.
Thank you for your attention, dear reader.

--
Dmitry

3 comments:

Unknown said...

Another (more simple?) way would be to use a combination of native LoadRunner parameters, such as the Vuser ID, Iteration NUmber and Date/Time parameter types already available.

for example:
{vuserid}{iter_number}{dtstamp}.zip would achieve the same if u used native LoadRunner parameter types, without having to write additional C code.

Also, to get milliseconds with the Date/Time parameter just use the .000 format.

for example:
%Y%m%d%H%M%S.000 => 20080602235312.815

Regards,
Tim

Anonymous said...

Hi Dmitry-

You may want to take a look at the web_save_timestamp_param function, which saves the timestamp in milliseconds to a LoadRunner parameter.

Charlie

Unknown said...

HiDmitry,
Thank you very much for the post.
I have read your article on "How to get unique file name in Loadrunner". I have a query in this, we use the following function to save a PDF file for one virtual user.
fp = fopen "c:\\temp\\file.pdf","wb");

Can we use Parameterization for the variable "file.pdf" from the above function,(as "file1.pdf,file2.pdf...so on)
and after if we execute the script with multiple users, it saves all the PDF files with different names.So by doing this can we skip programming part as you explained in "How to get unique file name in Loadrunner".
Please let me know will this solution works.

Thanks
Satya