Wednesday, November 25, 2009
Monday, October 19, 2009
Google Translation Perfected The Art of Lost In Translation
Koorts is weg, maar zo slap als een vaatdoek. Mis voor het eerst in lange tijd een TV. Beetje zinloos zappen bij de kachel lijkt me heerlijk
http://twitter.com/silvertje/status/4998571402
Google Translation sez: Fever is gone, but as limp as a dish cloth. Mass for the first time in a long time TV. Bit pointless zapping the stove seems wonderful
har3 - omg ...
http://twitter.com/silvertje/status/4998571402
Google Translation sez: Fever is gone, but as limp as a dish cloth. Mass for the first time in a long time TV. Bit pointless zapping the stove seems wonderful
har3 - omg ...
Friday, September 11, 2009
Thursday, September 10, 2009
Persisting LR Data Using MySQL
In the beginning it was horrible: not knowing what kind of C compiler LoadRunner is using, I experience with several header files from cygwin and mingw, which I know, deep inside, won’t work.
But RTFM saved the day, by merging the header files to $LR/include MySQL C code can be compiled by only tweaking one 64 bits reference.
Below is the final code to commit unique users, I totally rely on MySQL’s ACID to do the right thing. Hopefully I put my belief at the right place.
GetUniqueUserName
But RTFM saved the day, by merging the header files to $LR/include MySQL C code can be compiled by only tweaking one 64 bits reference.
Below is the final code to commit unique users, I totally rely on MySQL’s ACID to do the right thing. Hopefully I put my belief at the right place.
The final result: running 90 virtual users (I ran out of login), each running 20 seconds transactions.int commit_user() {
int rc = 0;
char *exec;
int good = 0;
int available = 1;
db_connection = mysql_init(NULL);
if (db_connection == NULL) {
lr_error_message("Insufficient memory");
return -1;
}
// Connect to the database
if (mysql_real_connect(db_connection, server, user, password, database, port, NULL, 0) == NULL) {
lr_error_message("error on connect: %s", mysql_error(db_connection));
mysql_close(db_connection);
return -1;
}
lr_output_message("Connection to DB is established");
while (!good) {
available = 1;
while (available) {
exec = lr_eval_string("SELECT EXISTS (select login from LATLogin WHERE login = '{pUserName}');");
if (mysql_query(db_connection, exec)!= 0) {
lr_error_message("%s;error on query: %s", exec, mysql_error(db_connection));
mysql_close(db_connection);
return -1;
}
lr_output_message("exec: %s", exec);
if ((query_result = mysql_store_result(db_connection)) == NULL) {
lr_error_message("%s;error on store: %s", exec, mysql_error(db_connection));
mysql_close(db_connection);
return -1;
}
result_row = mysql_fetch_row(query_result);
available = atoi(result_row[0]);
lr_output_message("available=%d", available);
if (available) { //exists
lr_advance_param("pDataFileUserName");
lr_output_message("Advance pDataFileUserName = %s", lr_eval_string("{pDataFileUserName}"));
while (strcmp(lr_eval_string("{pDataFileUserName}"), lr_eval_string("{pUserName}")) == 0) {
lr_advance_param("pDataFileUserName");
lr_output_message("Advance pDataFileUserName = %s", lr_eval_string("{pDataFileUserName}"));
}
lr_save_string(lr_eval_string("{pDataFileUserName}"), "pUserName");
}
mysql_free_result(query_result);
}
exec = lr_eval_string("INSERT INTO LATLogin VALUES('{pUserName}');");
if (mysql_query(db_connection, exec)!= 0) {
rc = mysql_errno(db_connection);
if (rc == 1062) {
lr_output_message("%s is too late, duplicate exists", exec);
//when pUserName exists, probably some else took it already
lr_advance_param("pDataFileUserName");
lr_output_message("Advance pDataFileUserName = %s", lr_eval_string("{pDataFileUserName}"));
while (strcmp(lr_eval_string("{pDataFileUserName}"), lr_eval_string("{pUserName}")) == 0) {
lr_advance_param("pDataFileUserName");
lr_output_message("Advance pDataFileUserName = %s", lr_eval_string("{pDataFileUserName}"));
}
lr_save_string(lr_eval_string("{pDataFileUserName}"), "pUserName");
}
else {
lr_error_message("%s, error(%d): %s", exec, mysql_errno(db_connection), mysql_error(db_connection));
mysql_close(db_connection);
return -1;
}
}
else {
lr_output_message("exec: %s", exec);
good = 1;
user_removed = 0;
}
}
mysql_close(db_connection);
lr_output_message("Connection to DB is closed");
return 0;
}
GetUniqueUserName
- 75% of population: 0.028 +/- 0.02
- 90Percentile: 0.043
Tuesday, September 8, 2009
Perl Now Runs On Android Scripting Environment (ASE)
I think I have heard about it before, but I managed to push it down to my subconscious level. Now off to figure out which android phone to throw into the ring of my gadget wishlist.
Sunday, September 6, 2009
Internet Is Humming Fine
The tech is a magician! He fixed AT&T's crappy DSL line. No red DSL light blinking this week, not once.
DSL Training Errors, Time Since Last Event: 5 days 6:51:19
DSL Training Errors, Time Since Last Event: 5 days 6:51:19
House of Prime Rib
1906 Van Ness Ave
San Francisco, CA 94109
Tel:(415) 885-4605
http://houseofprimerib.net
They are doing a good imitation of Lawry's, or is it the other way around?
San Francisco, CA 94109
Tel:(415) 885-4605
http://houseofprimerib.net
They are doing a good imitation of Lawry's, or is it the other way around?
Friday, September 4, 2009
RTFM Saved The Day
Friday afternoon, and I am very down since nothing works.
I admit, Wilsonmar webpage's not the official one, but it's damn close. But then, I noticed this:
I admit, Wilsonmar webpage's not the official one, but it's damn close. But then, I noticed this:
LoadRunner usesMySQL C code is compiling nicely now (after one 64bits ref is tweaked).1994 GNU C Pre-Processor options and the
1995 LCC-win32 Retargetable C Compiler/Linker from the Free Software Foundation via Chris Fraser of AT&T and Dave Hanson of Princeton.
The New Multi Protocol Script On LR9.1 Is A Useless POS
Q: Can I record ODBC traffic for Action1.c and then record Web traffic for Action2.c (or vice versa)?
A: No.
A: No.
Thursday, September 3, 2009
El Burro's Mexican Restaurant
1875 S Bascom Ave # 570 (The Pruneyard #570)
Campbell, CA 95008-2389
Tel: (408) 371-5800
Not bad, not bad at all
Campbell, CA 95008-2389
Tel: (408) 371-5800
Not bad, not bad at all
Next Stop: SQLite
Actually no, I was thinking about something more ambitious (MySQL). The fact that I have to hunt down other C library files, forces me to consider SQLite. Just drop sqlite3.dll to $LR/bin, sqlite3.h to $LR/include and trim off the 64 bit references in sqlite3.h to make it works.
But simpler solution doesn’t make my life easier, since writing SQLite code (or any db code), in C, that doesn’t leak memory or crashes the db, is fairly hard.
But finally, I get this:
But simpler solution doesn’t make my life easier, since writing SQLite code (or any db code), in C, that doesn’t leak memory or crashes the db, is fairly hard.
But finally, I get this:
Functionally the script works, at 50 virtual users, each running 20 seconds transactions, even the GetUniqueUserName transaction is fairly fast:rc = sqlite3_open("test.db", &db);
if (rc) {
lr_output_message("Can't open database: %s", sqlite3_errmsg(db));
sqlite3_close(db);
return -1;
}
exec = "NO RESULT QUERY SUCH AS: DELETE, INSERT”;
isPrepared = 0;
while (!isPrepared) {
rc = sqlite3_prepare(db, exec, -1, &stmt, 0);
if (rc == SQLITE_OK) { //SQLITE_OK == 0
isPrepared = 1;
isExecuted = 0;
while (!isExecuted) {
rc = sqlite3_step(stmt);
/* uncomment this section when exec is a query that return result
while ((rc == SQLITE_ROW)||(rc == SQLITE_BUSY) ) {
if (rc == SQLITE_BUSY ) {
lr_output_message("SQLITE_BUSY - wait for 0.1 seconds");
lr_think_time(0.1); // TODO: tweak the wait time to your need
}
else {
// extract data
rc = sqlite3_step(stmt);
}
}
*/
if (rc == SQLITE_DONE) {
isExecuted = 1;
sqlite3_finalize(stmt);
}
else if (rc == SQLITE_BUSY) { // DB is locked
lr_output_message("SQLITE_BUSY - wait for 0.1 seconds");
lr_think_time(0.1); // TODO: tweak the wait time to your need
}
else { // real bad stuff usually happens here
lr_output_message("Cannot execute step, rc = %d", rc);
lr_output_message("sqlite3_errmsg: %s", sqlite3_errmsg(db));
lr_output_message("sqlite3_extended_errcode, rc = %d", sqlite3_extended_errcode(db));
sqlite3_finalize(stmt);
sqlite3_close(db);
return -1;
}
}
}
else if (rc == SQLITE_BUSY) { // DB is locked
lr_output_message("SQLITE_BUSY - wait for 0.1 seconds");
lr_think_time(0.1); // TODO: tweak the wait time to your need
}
else { // real bad stuff usually happens here
lr_output_message("Could not prepare statement, rc=%d", rc);
lr_output_message("sqlite3_errmsg: %s", sqlite3_errmsg(db));
lr_output_message("sqlite3_extended_errcode, rc = %d", sqlite3_extended_errcode(db));
sqlite3_close(db);
return -1;
}
}
sqlite3_close(db);
- 75% of population: 0.269 +/- 0.731
- 90Percentile: 0.655
Wednesday, September 2, 2009
ActiveState - People Don't Like You?
This is the first time I heard about people emitting strong comments against ActiveState, but I agree with Dami, ActiveState has been making my life very productive, it's products and business practices has been very satisfactory to me.
Monday, August 31, 2009
Cable Problem Causing The Internet To Fritz
Today, the DSL just decided not to work - again - ever. A technician is scheduled and he replaces the cable and everything works - so far.
Friday, August 28, 2009
LoadRunner Doesn't Like 64 Bit Emulation
LoadRunner doesn't like 64 bit emulation over 32 bit machine. It doesn't like long long declaration on .h header file. It spews:
invalid use of `long'Thus begin the hacking and slashing of sqlite3.h
Wednesday, August 26, 2009
Each VUser Must Use Unique Login ID
This is a problem: the web app that I am testing is using the login id as session id. Since I am furnished with data, that has multiple non-unique logins, I have to make sure that all of virtual users are using unique login id.
Several solutions come to mind, but I decided to give LoadRunner VTS a whirl.
Perusing VTS2.doc I quickly hone in lrvtc_send_if_unique function:
Functionally the script works, but VTS system is not capable of handling multiple virtual users. At 10 virtual users, each running 20 seconds transactions, VTS is throwing numerous -10003 errors, that causes slow GetUniqueUserName transaction:
Several solutions come to mind, but I decided to give LoadRunner VTS a whirl.
Perusing VTS2.doc I quickly hone in lrvtc_send_if_unique function:
VTCERR lrvtc_send_if_unique(char *columnName, char *message)But this function is pretty much useless since the VTCERR equals 1 no matter if the insertion is successful or not. Trying its cousin instead:
VTCERR vtc_send_if_unique(PVCI pvci, char *columnName, char *message, unsigned short *outRc)This function returns successful insertion status in outRc parameter (1 = Pass, 0 = Fail).
The login removal process is a trickier than the insert process, since VTS doesn’t have a function to look up a value in a column, a value has to be looked up (one by one):lr_start_transaction("GetUniqueUserName");
status = 0;
while (status == 0) {
lr_save_string(lr_eval_string("{pDATAFILEUserName}"), "pUserName");
pvci = lrvtc_connect(lr_eval_string("{pVTSServer}"), 8888, 0);
rc = vtc_send_if_unique(pvci, "pUserName1", lr_eval_string("{pUserName}"), &status);
lr_output_message("Insert if unique, rc = %d, status: = %d", rc, status);
lrvtc_disconnect();
if (status == 0) //try another login in the data file if fail
lr_advance_param("pDATAFILEUserName ");
else
user_removed = 0; // just another flag
}
lr_end_transaction("GetUniqueUserName", LR_AUTO);
A little explanation about lastrowID, when a data is deleted from VTS, a value can never be re-inserted into that row again via vtc_send_if_unique function. So, there are lots of empty rows at the lower index after the value is deleted. Thus there is no point for the script to start the search for a login to delete from row 1; instead it should start the search from the last deletion point.int removePreviousUserName() { // to eliviate the nasty side effect of exit when error
int rc = 0;
unsigned short status;
int EOT = 0;
int i;
int user_removed = 0;
lr_start_transaction("RemovePreviousUserName");
i=lastrowID;
while (!EOT) {
i++;
pvci = lrvtc_connect(lr_eval_string("{pVTSServer}"), 8888, 0);
rc = lrvtc_query_column("pUserName1", i);
lr_output_message("query row %d, rc = %d", i, rc);
if (rc!=0)
EOT = 1;
else {
if (stricmp(lr_eval_string("{pUserName}"), lr_eval_string("{pUserName1}")) == 0) {
lr_output_message("Del msg (%s) at row %d", lr_eval_string("{pUserName1}"), i);
rc = vtc_clear_message(pvci, "pUserName1", i, &status);
lr_output_message("Del msg, rc = %d, Status = %d", rc, status);
lastrowID = i;
EOT = 1; // exit anyway
user_removed = 1;
}
}
lrvtc_disconnect();
}
lr_end_transaction("RemovePreviousUserName", LR_AUTO);
return user_removed;
}
Functionally the script works, but VTS system is not capable of handling multiple virtual users. At 10 virtual users, each running 20 seconds transactions, VTS is throwing numerous -10003 errors, that causes slow GetUniqueUserName transaction:
- 75% of population: 2.201 +/- 2.912
- 90 Percentile: 6.506
Subscribe to:
Posts (Atom)